文章目录
-
- 1. 数组的概念
- 2. 一维数组的创建和初始化
-
- 2.1 数组创建
- 2.2 数组的初始化
- 2.3 数组的类型
- 3. 一维数组的使用
-
- 3.1 数组下标
- 3.2 数组元素的打印
- 3.3 数组的输入
- 4. 一维数组在内存中的存储
- 5. sizeof计算数组元素个数
- 6. 二维数组的创建
-
- 6.1 二维数组的概念
- 6.2 二维数组的创建语法
- 7. 二维数组的初始化
-
- 7.1 不完全初始化
- 7.2 完全初始化
- 7.3 按照行初始化
- 7.4 省略行的初始化
- 8. 二维数组的使用
-
- 8.1 二维数组的下标
- 8.2 二维数组的输入和输出
- 9. 二维数组在内存中的存储
- 10. C99中的变长数组
-
- 10.1 传统数组的限制
- 10.2 变长数组的特性
- 11. 数组练习
-
- 11.1 练习1:多个字符从两端移动,向中间汇聚
- 11.2 练习2:二分查找
1. 数组的概念
数组是一组相同类型元素的集合,从中可以提炼两个关键信息:
数组分为一维数组和多维数组,日常使用中以二维数组最为常见。
2. 一维数组的创建和初始化
2.1 数组创建
一维数组创建的基本语法如下:
type arr_name[常量值];
- type:指定数组中元素的数据类型,如char、short、int、float等
- arr_name:数组名,可根据需求自定义有意义的名称
- []中的常量值:指定数组的元素个数
示例:
// 存储20人的数学成绩
int math[20];
// 存储8个字符
char ch[8];
// 存储10个浮点型分数
double score[10];
2.2 数组的初始化
数组创建时给定初始值的操作称为初始化,通常使用 大括号{} 完成。
完全初始化:所有元素都赋予初始值
int arr[5] = {1,2,3,4,5};
不完全初始化:只给部分元素赋值,未赋值的元素默认初始化为0
int arr2[6] = {1};// 第一个元素为1,剩余5个元素为0
错误初始化:初始化的元素个数超过数组的大小
// 错误:数组大小为3,初始化项有4个
int arr3[3] = {1, 2, 3, 4};
省略大小初始化:数组初始化时可省略大小,编译器会根据初始化项的个数确定数组大小
int arr4[] = {1,2,3};// 数组大小为3
2.3 数组的类型
数组属于自定义类型,去掉数组名后剩下的部分就是数组的类型。
示例:
int arr1[10];// 数组类型:int [10]
int arr2[12];// 数组类型:int [12]
char ch[5];// 数组类型:char [5]
3. 一维数组的使用
3.1 数组下标
C语言规定数组的下标从0开始,假设数组有n个元素,最后一个元素的下标为n-1。例如:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};

数组提供了 下标引用操作符[] 来访问元素,语法为数组名[下标]。
示例:
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
// 访问下标为7的元素,值为8
printf("%d\\n", arr[7]);
// 访问下标为3的元素,值为4
printf("%d\\n", arr[3]);
return 0;
}
输出结果:
8
4
3.2 数组元素的打印
通过for循环生成所有元素的下标,即可遍历打印整个数组。
示例:
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
输出结果:
1 2 3 4 5 6 7 8 9 10
3.3 数组的输入
使用scanf配合下标引用操作符,可给数组元素输入数据。
示例:
#include <stdio.h>
int main()
{
int arr[10] = {0};
int i = 0;
// 输入数据
for(i = 0; i < 10; i++)
{
scanf("%d", &arr[i]);
}
// 输出数据
for(i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
输入输出结果:
0 2 4 6 8 1 3 5 7 9
0 2 4 6 8 1 3 5 7 9
4. 一维数组在内存中的存储
通过打印数组每个元素的地址,可以观察数组在内存中的存储规律。
示例代码:
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i = 0; i < 10; i++)
{
printf("&arr[%d] = %p\\n ", i, &arr[i]);
}
return 0;
}
输出结果:
根据上述结果,数组元素的地址随着下标的增长由小到大变化,且相邻元素的地址差值为4个字节(对应int类型的大小) 所以可以得出结论:一维数组在内存中是连续存放的
5. sizeof计算数组元素个数
sizeof是C语言的关键字,可计算类型或变量所占内存的大小(单位:字节),也能计算整个数组的总大小。
计算原理:
- 数组总大小 = sizeof(数组名)
- 单个元素大小 = sizeof(数组名[0])
- 元素个数 = 数组总大小 / 单个元素大小= sizeof(数组名)/sizeof(数组名[0])
示例代码:
#include <stdio.h>
int main()
{
int arr[10] = {0};
printf("%zd\\n", sizeof(arr)); // 计算数组总大小,结果为40
printf("%zd\\n", sizeof(arr[0])); // 计算单个元素大小,结果为4
printf("%zd\\n", sizeof(arr)/sizeof(arr[0])); // 计算元素个数,结果为10
return 0;
}
注意:使用%zd作为sizeof计算结果的占位符,适配size_t类型
6. 二维数组的创建
6.1 二维数组的概念
二维数组可以理解为数组的数组,即把一维数组作为元素,组成一个新的数组。 同理,二维数组为元素的数组被称为三维数组,二维及以上数组统称为多维数组。
6.2 二维数组的创建语法
type arr_name[常量值1][常量值2];
- 常量值1:表示二维数组的行数
- 常量值2:表示二维数组的列数
- type:表示数组元素的数据类型
示例:
// 3行5列的整型二维数组
int arr[3][5];
// 2行8列的浮点型二维数组
double data[2][8];
7. 二维数组的初始化
二维数组的初始化同样使用大括号{},支持多种初始化方式。
7.1 不完全初始化
只给部分元素赋值,未赋值的元素默认初始化为0
// 第一行前两个元素为1、2,其余元素为0
int arr1[3][5] = {1, 2};
// 所有元素初始化为0
int arr2[3][5] = {0};
7.2 完全初始化
按行顺序给所有元素赋值
int arr3[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
7.3 按照行初始化
使用嵌套大括号,明确每一行的初始值
// 第一行:1、2;第二行:3、4;第三行:5、6;其余元素为0
int arr4[3][5] = {{1,2},{3,4},{5,6}};
7.4 省略行的初始化
初始化时可以省略行数,但不能省略列数,编译器会根据初始化项自动计算行数
int arr5[][5] = {1,2,3};
int arr6[][5] = {1,2,3,4,5,6,7};
int arr7[][5] = {{1,2}, {3,4}, {5,6}};
8. 二维数组的使用
8.1 二维数组的下标
二维数组通过行下标和列下标来访问元素,行和列的下标都从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};
// 访问第2行第4列的元素,值为7
printf("%d\\n", arr[2][4]);
return 0;
}
输出结果:
7
8.2 二维数组的输入和输出
使用双层for循环遍历二维数组:外层循环控制行,内层循环控制列。
示例代码:
#include <stdio.h>
int main()
{
int arr[3][5] = {0};
int i = 0;
// 输入数据
for(i = 0; i < 3; i++)
{
int j = 0;
for(j = 0; j < 5; j++)
{
scanf("%d", &arr[i][j]);
}
}
// 输出数据
for(i = 0; i < 3; i++)
{
int j = 0;
for(j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
// 每行输出完换行
printf("\\n");
}
return 0;
}
9. 二维数组在内存中的存储
通过打印二维数组所有元素的地址,可观察其内存存储规律。
示例代码:
#include <stdio.h>
int main()
{
int arr[3][5] = { 0 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("&arr[%d][%d] = %p\\n", i, j, &arr[i][j]);
}
}
return 0;
}
输出结果分析:
10. C99中的变长数组
10.1 传统数组的限制
C99标准之前,数组的大小必须用常量或常量表达式指定,无法使用变量,灵活性不足。
// 合法
int arr1[10];
int arr2[3+5];
// 合法(初始化时省略大小)
int arr3[] = {1,2,3};
10.2 变长数组的特性
C99引入变长数组(VLA),允许使用变量指定数组大小,数组长度在运行时确定。
int n = 5;
// 变长数组,n的值决定数组大小
int arr[n];
注意事项:
示例代码(GCC下运行):
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int arr[n];
int i = 0;
// 输入数据
for (i = 0; i < n; i++)
{
scanf("%d", &arr[i]);
}
// 输出数据
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
11. 数组练习
11.1 练习1:多个字符从两端移动,向中间汇聚
功能:演示字符串从两端向中间逐步显示的效果
#include <stdio.h>
#include <string.h>
// Sleep函数需要的头文件,Windows系统下使用
#include <windows.h>
int main()
{
char arr1[] = "welcome to bit…";
char arr2[] = "#################";
int left = 0;
int right = strlen(arr1)–1;
printf("%s\\n", arr2);
while(left<=right)
{
// 休眠1秒
Sleep(1000);
arr2[left] = arr1[left];
arr2[right] = arr1[right];
left++;
right—;
printf("%s\\n", arr2);
}
return 0;
}
11.2 练习2:二分查找
功能:在升序整型数组中高效查找指定值,找到返回下标,否则提示找不到
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int left = 0;
int right = sizeof(arr)/sizeof(arr[0])–1;
// 要查找的数字
int key = 7;
// 记录中间元素下标
int mid = 0;
// 标记是否找到
int find = 0;
while(left <= right)
{
// 计算中间下标,避免left+right溢出
mid = left + (right – left) / 2;
if(arr[mid] > key)
{
// 目标值在左半区间
right = mid–1;
}
else if(arr[mid] < key)
{
// 目标值在右半区间
left = mid+1;
}
else
{
// 找到目标值
find = 1;
break;
}
}
if(1 == find)
printf("找到了,下标是%d\\n", mid);
else
printf("找不到\\n");
return 0;
}



