C 语言笔记:数组
一、数组的概念
数组是若干个相同类型的变量在内存中有序存储的集合。
- 数组用于存储一组数据
- 数组里面存储的数据类型必须是相同的
- 数组在内存中会开辟一块连续的空间
int [a]
定义了一个整型的数组 a ,a 是数组的名字,数组中有 10 个元素,每个元素的类型都是 int 类型,而且在内存中连续存储。
这 10 个元素分别是 a[0]
, a[1]
, a[2]
, ..., a[9]
.
一个 int 型变量占 4 个字节,int a[10]
占 \(4 \times 10 = 40\) 个字节。
二、数组的分类
(一)按元素类型分
- 字符数组:
char s[10]
- 短整型的数组:
short int a[10]
- 整型的数组:
int a[8]
- 长整型的数组:
long int a[9]
- 浮点型的数组(单、双):
float a[12]
,double a[10]
- 指针数组:
char *a[10]
,int *a[10]
- 结构体数组:
struct stu boy[10]
(二)按维数分
- 一维数组
int a[30];
- 二维数组
int a[2][30];
有 2 行、30 列
二维数组由多个一维数组构成 - 多维数组
int a[4][2][10];
三维数组由多个相同的二维数组构成
三、定义数组
(一)定义一维数组
格式:数据类型 数组名[元素个数];
例子:int a[10];
注意:数组元素的个数在定义的时候可以不写,但是如果不写,必须初始化(定义的时候赋值)。
#include <stdio.h>
int main()
{
// 定义一个一维数组
int a[10];
// 通过 sizeof 关键字可以获取数组的大小
printf("sizeof(a) = %d %d\n", sizeof(a), 10 * sizeof(int));
// 定义数组的同时赋值(初始化)
int b[] = {10, 20, 30};
printf("sizeof(b) = %d\n", sizeof(b));
return 0;
}
运行结果:
sizeof(a) = 40 40
sizeof(b) = 12
分别为 40 字节和 12 字节
(二)定义二维数组
格式:数据类型 数组名[行数][列数];
例子:int a[2][4];
,定义一个名为 a 的二维数组,每一个元素都是 int 类型,2 行 4 列,共 \(2 \times 4 = 8\) 个元素。
注意:
(1)二维数组也是连续开辟空间。
(2)访问元素都是从 0 行和 0 列开始:a[0][0], a[0][1], a[0][2], a[0][3], a[1][0], a[1][1], a[1][2], a[1][3].
(3)二维数组的下标也可以省略,但是有条件。在初始化时,二维数组的行数可以省略,但列数不能省略。
#include <stdio.h>
int main()
{
// 定义一个二维数组
int b[2][4];
printf("sizeof(b) = %d %d\n", sizeof(b), 2 * 4 * sizeof(int));
// int c[][];会报错
// int c[][] = {1, 2, 3, 4, 5};会报错
// int c[3][] = {1, 2, 3, 4, 5};会报错
int c[][4] = {1, 2, 3, 4, 5};
printf("sizeof(c) = %d\n", sizeof(c));
int d[][4] = {{1, 2, 3, 4}, {5, 0, 0, 0}};
printf("sizeof(d) = %zu\n", sizeof(d));
return 0;
}
运行结果:
sizeof(b) = 32 32
sizeof(c) = 32
sizeof(d) = 32
-
对于第一个数组
c[][4]
,由于没有提供足够的初始化数据,编译器会尽量填充,而缺失的部分会被补充为 0。这导致该数组实际上包含了两个一维数组,每个一维数组有4个元素。因此,sizeof(c)
的结果是 \(4 \times 4 \times 2 = 32\) 字节。 -
对于第二个数组
d[][4]
,提供了完整的初始化数据,包含两个一维数组,每个一维数组有 4 个元素。因此,sizeof(d)
的结果同样是 \(4 \times 4 \times 2 = 32\) 字节。
int c[][4] = {1, 2, 3, 4, 5};
是一个 1 行 4 列的数组。
四、定义并初始化
开辟空间的同时给变量赋值。
(一)一维数组初始化
如果不初始化,将得到随机值的数组
#include <stdio.h>
int main()
{
// 一维数组的初始化
int a[4];//得到随机值
printf("%d\n", a[0]);
printf("%d\n", a[1]);
printf("%d\n", a[2]);
printf("%d\n", a[3]);
return 0;
}
运行结果:
-1265888272
530
0
0
- 全部初始化
#include <stdio.h>
int main()
{
// 全部初始化
int a[4] = {523, 253, 46, 9};
printf("%d\n", a[0]);
printf("%d\n", a[1]);
printf("%d\n", a[2]);
printf("%d\n", a[3]);
return 0;
}
运行结果:
523
253
46
9
- 部分初始化
#include <stdio.h>
int main()
{
// 全部初始化
int a[4] = {15, 6};
printf("%d\n", a[0]);
printf("%d\n", a[1]);
printf("%d\n", a[2]);
printf("%d\n", a[3]);
return 0;
}
运行结果:
15
6
0
0
没有初始化的元素自动补 0 .
(二)二维数组初始化
如果不初始化,得到的都是随机值:
#include <stdio.h>
int main()
{
// 二维数组初始化
int a[2][3];// 得到随机值
printf("%d\n", a[0][0]);
printf("%d\n", a[0][1]);
printf("%d\n", a[0][2]);
printf("%d\n", a[1][0]);
printf("%d\n", a[1][1]);
printf("%d\n", a[1][2]);
return 0;
}
运行结果:
0
0
93
0
-71298048
527
- 按行初始化
(1) 全部初始化
#include <stdio.h>
int main()
{
// 按行初始化
// 全部初始化
int a[2][3] = {{10, 20, 30}, {66, 77, 888}};
printf("%d\n", a[0][0]);
printf("%d\n", a[0][1]);
printf("%d\n", a[0][2]);
printf("%d\n", a[1][0]);
printf("%d\n", a[1][1]);
printf("%d\n", a[1][2]);
return 0;
}
运行结果:
10
20
30
66
77
888
(2) 部分初始化:没有初始化的位置自动填 0
#include <stdio.h>
int main()
{
// 按行初始化
// 部分初始化
int a[2][3] = {{10, 20}, {66}};
printf("%d\n", a[0][0]);
printf("%d\n", a[0][1]);
printf("%d\n", a[0][2]);
printf("%d\n", a[1][0]);
printf("%d\n", a[1][1]);
printf("%d\n", a[1][2]);
return 0;
}
运行结果:
10
20
0
66
0
0
- 逐步初始化
(1) 全部初始化
#include <stdio.h>
int main()
{
// 逐个初始化
// 全部初始化
int a[2][3] = {1, 2, 3, 4, 5, 6};
printf("%d\n", a[0][0]);
printf("%d\n", a[0][1]);
printf("%d\n", a[0][2]);
printf("%d\n", a[1][0]);
printf("%d\n", a[1][1]);
printf("%d\n", a[1][2]);
return 0;
}
运行结果
1
2
3
4
5
6
(2) 部分初始化:没有初始化的位置自动填 0
#include <stdio.h>
int main()
{
// 逐个初始化
// 全部初始化
int a[2][3] = {1, 2, 3};
printf("%d\n", a[0][0]);
printf("%d\n", a[0][1]);
printf("%d\n", a[0][2]);
printf("%d\n", a[1][0]);
printf("%d\n", a[1][1]);
printf("%d\n", a[1][2]);
return 0;
}
运行结果:
1
2
3
0
0
0
五、数组元素的引用方式
(一)一维数组的引用方法
数组名[下标];//下标表示元素在数组中的位置
注意:从 0 开始引用
int a[10];
a[2];
用 for 循环引用一维数组:
#include <stdio.h>
int main()
{
// 一维数组的引用以及一维数组的遍历
int a[6] = {111, 222, 333, 444, 555, 666};
// 一维数组的遍历
int i;
for(i = 0; i < sizeof(a) / sizeof(int); i++)
{
printf("a[%d] = %d\n", i, a[i]);
}
return 0;
}
sizeof(a)
返回数组 a 所占空间;sizeof(int)
返回整型数组每个元素所占大小;sizeof(a) / sizeof(int)
返回数组 a 的元素个数。
运行结果:
a[0] = 111
a[1] = 222
a[2] = 333
a[3] = 444
a[4] = 555
a[5] = 666
(二)二维数组的引用方法
#include <stdio.h>
int main()
{
// 二维数组的引用以及二维数组的遍历
int b[3][4] = {1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12};
// 二维数组的遍历
int m, n;
// 外层循环控制行
for (m = 0; m < 3; m++)
{
//内层循环控制列
for (n = 0; n < 4; n++)
{
printf("%-4d", b[m][n]);
}
printf("\n");// 每行输出结束后换行
}
return 0;
}
%-4d
表示输出宽度为 4 左对齐的整型。
运行结果:
1 2 3 4
5 6 7 8
9 10 11 12
六、字符数组的定义和初始化
定义下面 4 个字符数组:
char c1[] = {'c', ' ', 'p', 'r', 'o', 'g'};
char c2[] = "c prog";
char c3[][5] = {
{'B', 'A', 'S', 'I', 'C'},
{'d', 'B', 'A', 'S', 'E'}
};
char c4[][6] = {"hello", "world"};
让我们分别分析这四个数组在内存中的存放情况:
- 对于
char c1[] = {'c', ' ', 'p', 'r', 'o', 'g'};
:c1[0] c1[1] c1[2] c1[3] c1[4] c1[5] 'c' ' ' 'p' 'r' 'o' 'g' - 对于
char c2[] = "c prog";
:c2[0] c2[1] c2[2] c2[3] c2[4] c2[5] c2[6] 'c' ' ' 'p' 'r' 'o' 'g' '\0'
\0
是空字符
-
对于
char c3[][5]
:c3[0][0] c3[0][1] c3[0][2] c3[0][3] c3[0][4] 'B' 'A' 'S' 'I' 'C' c3[1][0] c3[1][1] c3[1][2] c3[1][3] c3[1][4] 'd' 'B' 'A' 'S' 'E' -
对于
char c4[][6] = {"hello", "world"};
:c4[0][0] c4[0][1] c4[0][2] c4[0][3] c4[0][4] c4[0][5] 'h' 'e' 'l' 'l' 'o' '\0' c4[1][0] c4[1][1] c4[1][2] c4[1][3] c4[1][4] c4[1][5] 'w' 'o' 'r' 'l' 'd' '\0'
总结:每个字符占用一个字节,字符串以空字符 '\0'
结尾。对于字符数组,如果没有明确指定大小,编译器会根据初始化的元素个数确定数组大小。对于二维字符数组,第一维大小为数组元素个数,第二维大小为字符个数。
#include <stdio.h>
int main()
{
// 定义一个字符数组,通过 scanf 函数输入字符串并输出结果
// 通过赋值""这样的方式可以清除字符数组中的垃圾字符,让每个元素都是\0
char ch[32] = "";
// 数组名就是当前数组的首地址。所以 scanf 的第二个参数直接传数组名
scanf("%s", ch);
printf("ch = %s\n", ch);
return 0;
}
在 Qt 中使用 scanf
,需要通过终端输入输出
回到『编辑』