数组的概念

数组是一组相同类型元素的集合。

  • 数组中元素个数不能为0.
  • 数组中数据类型是相同的。

一维数组的创建和初始化

一维数组的创建

语法格式如下:

1
type arr_name[常量值];

存放在数组的值称为数组的元素,数组在创建时可以指定数组的大小和数组的元

素类型。

比如:

1
int arr1[10] = { 0 };

一维数组的初始化

在数组创建时给数组一些初始值叫做初始化。

1
2
3
int arr1[3] = { 0,1,2 }; //完全初始化
int arr2[3] = { 0,1 }; //部分初始化,剩余元素自动初始化为0
//int arr3[3] = { 1,2,3,4 }; // 错误,初始化元素个数超过数组大小

数组的类型

1
2
3
int arr1[10]
int arr2[5]
char arr3[10]

一维数组的使用

数组下标

C语言中规定数组是有下标的,下标从0开始。假设数组有n个元素,那么第n个元

素的下标就是 n - 1 。

C语言为数组访问提供了操作符[],叫下标引用操作符。

1
2
3
4
5
6
7
8
int arr1[3] = { 0,1,2 }; 
char arr2[3] = { 'a','b','c'};
printf("%d\n", arr1[0]);
printf("%d\n", arr1[1]);
printf("%d\n", arr1[2]);
printf("%c\n", arr2[0]);
printf("%c\n", arr2[1]);
printf("%c\n", arr2[2]);

数组元素的打印

可以通过[]和循环来打印数组元素。

1
2
3
4
5
6
int arr1[3] = { 0,1,2 };
int i = 0;
for (i = 0;i <= 2;i++)
{
printf("%d ", arr1[i]);
}

数组元素的输入

可以通过[]和循环来写入数组元素的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
int arr1[3] = { 0 };
int i = 0;
for (i = 0;i <= 2;i++)
{
//循环写入数组元素
scanf("%d", &arr1[i]);
}

for (i = 0;i <= 2;i++)
{
// 循环打印数组元素
printf("%d ", arr1[i]);
}

一维数组在内存中的存储

这里简单研究一下,更深入的研究会在指针篇讲到。

1
2
3
4
5
6
int arr[5] = { 1,2,3,4,5 };
for (int i = 0;i <= 4;i++)
{
// 打印数组元素的地址
printf("%p\n", &arr[i]);
}

这里的地址是以十六进制存储的,可以看出每个元素之间的地址差值为4。(这是

一个整型数组,而一个整型时四个字节)。可以得出一个结论:数组元素在内存中

是连续存放。

sizeof 计算数组元素个数

当不确定数组元素个数时,可以使用 sizeof 辅助确定数组元素个数。

1
2
int arr[5] = { 1,2,3,4,5 };
printf("%zd\n", sizeof(arr));

这里计算得出结果是 20,即该数组元素所占总字节数。

所以可以通过 总字节数 / 单个元素所占字节数得出元素个数。

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

二维数组

二维数组的概念

把一维数组作为元素储存的数组称作二维数组。更高维数组依此类推。

二维数组的创建

语法格式与一维数组基本一致

1
2
// 二维数组的创建
int arr[3][5] = { 0 };
  • 3表示 arr 有 3 行
  • 5表示 arr 有 5 列
  • int 是数组元素类型

二维数组的初始化

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

这是二维数组的不完全初始化

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

在初始化二维数组时可以省略行但是不能省略列。

二维数组的使用

C语言规定,二维数组的行列都是从下标0开始。

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

二维数组的输入和输出

同一维数组类似,可以借助循环与[]进行输入输出。

1
2
3
4
5
6
7
8
9
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
for (int i = 0;i <= 2;i++)
{
for (int j = 0;j <= 4;j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int arr[2][3] = {0};
for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
{
for (int j = 0;j < sizeof(arr[0]) / sizeof(arr[0][0]);j++)
{
scanf("%d", &arr[i][j]);
}
}

for (int i = 0;i <= 1;i++)
{
for (int j = 0;j <= 2;j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;

二维数组在内存中的存储

1
2
3
4
5
6
7
8
int arr[2][3] = { 0 };
for (int i = 0;i < 2;i++)
{
for (int j = 0;j < 3;j++)
{
printf("%p\n", &arr[i][j]);
}
}


每一行内部的每个元素都是相邻的,和一维数组类似,每个元素之间的地址差值

为4。二维数组的元素在内存中也是连续存储的。

C99变长数组

在C99标准之前,C语言在创建数组的时候,数组大小的指定只能使用常量、常量

表达式。

C99中给了一个变长数组的新特性,允许使用变量指定数组大小。

1
2
3
4
5
int a = 0;
int b = 0;
int n = a + b;
scanf("%d%d", &a, &b);
int arr[n] = { 0 };

截止到2026-5-31, visual studio 2026 并没有支持 C99 中的变长数组。

二分查找

二分查找是一种很常见的算法。

原理:每次拿中间元素和目标数对比,砍掉一半查找范围,效率远高于挨个遍

历。

  • 中间值 < 目标:去右半边找
  • 中间值 > 目标:去左半边找
  • 相等:找到

条件:必须是在有序数组中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
int left = 0;
int right = sizeof(arr) / sizeof(arr[0]) - 1;
int aim = 3;
int flag = 0;// 是否找到的标志,0表示没有找到,1表示找到了
while (left <= right) // 当左边界小于等于右边界时继续循环,否则说明已经搜索完了整个数组还没有找到目标值
{
// 计算中间元素的索引
int mid = (left + right) / 2;
if (arr[mid] > aim)
{
// 如果中间元素大于目标值,说明目标值在左半部分
// 将右边界移动到中间元素的左边
right = mid - 1;
}
else if (arr[mid] < aim)
{
// 如果中间元素小于目标值,说明目标值在右半部分
// 将左边界移动到中间元素的右边
left = mid + 1;
}
else
{
printf("找到了,索引为%d\n", mid);
flag = 1;// 找到了,设置标志为1
break;
}
}
return 0;
}