C语言数组详解(附上原代码和图片详解)

C语言数组详解:基础向


<<当你需要处理一组相关的数据时,是选择定义100个独立变量,还是一个优雅的解决方案?

为什么数组如此重要?


在编程中,我们很少处理单个数据,想想如下场景:

  • 统计全班50名学生的成绩
  • 管理游戏中100个敌人的坐标
  • 存储1年中的温度数据

如果没有数组,将会这样写

int store1, score2, score3, ..., score50;//设定50个变量,管理起来很麻烦

有了数组,写起来就会变得简单:

int score[50];//清晰,简介,高效

本文将带你掌握:

  1. 一维数组的定义和使用
  2. 数组内存布局
  3. 二维数组的定义和使用

数组详细讲解(附有图示讲解)

  • C语言数组详解:基础向
    • 为什么数组如此重要?
  • 1、数组的概念
  • 2、一维数组的定义
    • 2.1 一维数组的创建
    • 2.2 一维数组的初始化
    • 2.3 一维数组的类型
  • 3、一维数组的使用
    • 3.1 访问数组元素
    • 3.2 一维数组元素的打印
    • 3.3 一维数组的输入
  • 4、一维数组的内存存储布局
      • 4.1 连续存储
    • 4.2 内存布局示意图
    • 4.3 数组连续存储的重要性
  • 5、使用sizeof计算数组大小
    • 5.1 语法形式
      • 5.1.1 计算总数组
      • 5.1.2 计算一个元素
      • 5.1.3 计算元素
    • 5.2 用sizeof来计算数组元素个数的好处
    • 5.3 使用注意事项
  • 6、二维数组
    • 6.1 二维数组的概念
    • 6.2 二维数组的创建
    • 6.3 二维数组的初始化
      • 1>不完全初始化
      • 2>完全初始化
    • 3>行初始化
      • 4>初始化时可省略行,但不能省略列
    • 7、二维数组的使用
      • 7.1 二维数组的下标
    • 7.2 二维数组的输入和输出
    • 7.3 二维数组在内存中的存储

1、数组的概念


上面了解到,数组是⼀组相同类型元素的集合,核心概念分为两点:

  1. 数组中存放的是1个或者多个数据,但是数组元素个数不能为0。
  2. 数组中存放的多个数据,类型是相同的。

数组分为⼀维数组和多维数组,多维数组⼀般⽐较多见的是⼆维数组。

2、一维数组的定义


2.1 一维数组的创建


一维数组的创建语法如下

tapy arr_name[常量]
//int arr[50];
  • tapy指的是基本数据类型,如:int(整形),char(字符型),double(浮点型)等等
  • arr_name是变量的名字,根据自己的定义,只要是有意义的就行
  • "[ ]"中的常量,使用来指定数组大小的,根据自己所需的需求来指定大小

通过以上三个核心要素,我们可以创建所需数组

int score[50]; //存储50名学生的成绩
char name[6];  //存储6个字符
int age[50];   //存储50名学生的年龄

2.2 一维数组的初始化


在基本数据类型[[基本数据类型#先定义,后初始化]]里举例过,变量可以在定义的同时初始化:

//基本数据类型的定义和初始化
int a = 10;
//数组的定义和初始化
int arr[5] = {1, 2, 3, 4, 5};//本质上是基本相同的

数组的初始化有两种

//完全初始化
int arr1[5] = {1, 2, 3, 4, 5};
//不完全初始化,未指定值默认为0
int arr2[5] = {1}; //{1, 0, 0, 0, 0}
//错误示范:初始值过
//int arr3[5] = {1, 2, 3, 4, 5, 6} //编译错误

2.3 一维数组的类型


数组去掉初始化,剩下的就是数组的类型。如:

//int类型
int arr1[5];
//char类型
char arr2[5];

3、一维数组的使用


3.1 访问数组元素

在C语言中,数组元素的下标从零开始。如果数组有n个元素,那么最后一个元素的下标就为n-1。数组的小标相当于数组指定元素的编号,案列如下:

int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

一维数组

  • 在C语言中,数组访问要加操作符"[ ]",这个操作符叫:下标应用操作符(类似于取地址符号*,这个到指针就细讲,这里先挖个坑)。
  • 有了下标访问操作符,我们就能够方便访问数组元素。

例如,要访问元素下标为4的元素,使用arr[4]。访问元素下标为8的元素,使用arr[8],如下所示:

#include<stdio.h>
int main()
{
	int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
	printf("arr[4] = %d\n",arr[4]);//5
	printf("arr[8] = %d\n",arr[8]);//9
	
	return 0;	
}

打印结果如下:

arr[4] = 5
arr[8] = 9

3.2 一维数组元素的打印


要访问数组的内容,我们可以访问所以的元素下标,通过使用for循环产生0-9的下标,进行打印元素数组。

代码如下:

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

输出结果:
在这里插入图片描述

3.3 一维数组的输入


明白了数组的访问,当然我们也根据需求,自己给数组输入想要的数据,但需要注意以下2点:

  • scanf会报警告,要在顶格使用#define _ CRT_SECURE_NO_WARNINGS。如果是VS编译器,则可以使用scanf_s。
  • 访问第几个元素并打印出来时,由于下标是n-1个,需要加上1,回到常量值。
    在这里插入图片描述

4、一维数组的内存存储布局


4.1 连续存储


int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

在内存中是这样存储的:
![[Pasted image 20251002100806.png]]

可以看出,数组在内存中是连续存储的。如果我们要深入了解数组,我们最好能了
解一下内存是什么?

  1. 打印元素的地址,要用%p打印,并用取地址符号&获取其数组元素地址
  2. 内存地址:每个内存单元都有一个唯一的地址,相当于房间的门牌号,可以通过门牌号快速查找指定元素
  3. 数据类型大小:不同的数据都有不同的内存大小,所占的内存空间也不一样,例如:char:1字节,int:4字节(这些内容我在[[基本数据类型#整形类型]]讲过)

4.2 内存布局示意图


在这里插入图片描述
内存是由低到高存储的

4.3 数组连续存储的重要性

性能层面

  • 缓存友好:减少CPU等待时间
  • 预取有效:硬件自动化
  • 内存管理:分配释放简单
  • 算法基础:高效数据结构的前提
  • 指针算术:C语言核心能力

5、使用sizeof计算数组大小


5.1 语法形式


sizeof(数据类型\变量)

sizeof是一个关键字,可以计算类型或者变量的内存大小的,sizeof也可以计算数组的大小

5.1.1 计算总数组


形式在[[基本数据类型#二、sizeof计算字节长度]]中有讲过。

#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,0,0,0,0,0 };
	
	printf("%zu\n", sizeof(arr));
	return 0;
}

输出结果如下:

这⾥输出的结果是40,计算的是数组所占内存空间的总⼤大小,单位是字节

5.1.2 计算一个元素


int main()
{
	int arr[10] = { 1,2,3,4,5 };
	
	printf("%zu\n", sizeof(arr[0]));
	return 0;
}

计算结果为:4

5.1.3 计算元素


我们又知道数组中所有元素的类型都是相同的,那只要计算出⼀个元素所占字节的个数,数组的元
个数就能算出来。这⾥我们选择第⼀个元素算大小就可以

int main()
{
	int arr[10] = { 1,2,3,4,5 };
	
	printf("%zu\n", sizeof(arr / arr[0]));
	return 0;
}

5.2 用sizeof来计算数组元素个数的好处


使用sizeof(arr) / sizeof(arr[0])计算数组元素有几个好处:

  1. 灵活性:数组中所有元素的类型都是相同的,适用于任何类型的数组
  2. 准确性:能计算出数组的元素个数,不用手动计算
  3. 可维护性:不管数组怎么变化,计算出的大小也随着变化

5.3 使用注意事项


  1. sizeof是运行符,不是函数
  2. sizeof返回的类型是size_t,输出格式应用%zu
  3. sizeof在编译时求值(除变长数组外)

正确理解和使用sizeof对于内存管理和程序优化非常重要。

6、二维数组


6.1 二维数组的概念


  • 前面的数组被称为一维数组,数组的元素都是内置类型的
  • 把一维数组做为数组的元素就是⼆维数组
  • ⼆维数组作为数组元素的数组被称为三维数组
  • ⼆维数组以上的数组统称为多维数组

6.2 二维数组的创建


type arr_name[常量值1][常量值2];

例如:
int arr[3][5];
double data[2][8];
  • 3表示数组有3行
  • 5表示每一行有5个元素
  • int表示数组的每个元素是整型类型
  • arr是数组名可以根据自己的需要指定名字

6.3 二维数组的初始化


1>不完全初始化

int arr1[3][5] = {1,2};
int arr2[3][5] = {0};

2>完全初始化


int arr3[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};

3>行初始化


int arr4[3][5] = {{1,2},{3,4},{5,6}};

4>初始化时可省略行,但不能省略列


int arr5[][5] = {1,2,3,4};
int arr6[][5] = {1,2,3,4,5,6,7,8};
int arr7[][5] = {{1,2}, {3,4}, {5,6}};

7、二维数组的使用


7.1 二维数组的下标


C语言规定,⼆维数组的行是从0开始的(红色部分),列也是从0开始的(蓝色部分)

我们可以清晰看到每个元素对应的门牌号,就可以准确打印数组中一个元素

#include<stdio.h>

int main()
{
	int arr[3][5] = {1,2,3,4,5,2,3,4,5,6,3,4,5,6,7};
	printf("%d\n",arr[3][2]);
	
	return0;
}

打印结果为:

6

7.2 二维数组的输入和输出


由于数组地址是连续存放的,二维数组也是如此。在输入时,过程和一维数组极其相似

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	//创建并初始化
	int arr[3][3] = {1,2,3,4,5,6,7,8,9};
	
	//输入二维数组
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			scanf("%d", &arr[i][j]);
		}
	}

	//打印二维数组
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

打印结果:

7.3 二维数组在内存中的存储


#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int main()
{
	int arr[3][3] = {1,2,3,4,5,6,7,8,9};

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("第arr[%d][%d]的内存为:%p ", j, i, &arr[i][j]);
			printf("\n");
		}
		printf("\n");
	}

	return 0;
}

输出内容如下:

从输出的结果来看,每个元素都是相邻的,地址之间相差4个字节,arr[0]和arr[1]之间也是差4个字节,所以⼆维数组中的每个元素都是连续存放的

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值