第27课 - 数组的本质分析
1. 数组的概念
数组是相同类型的变量的有序集合。
下图是一个包含5个int类型数据的数组的示意图:
2. 数组的大小
(1)数组在一片连续的内存中间存储元素
(2)数组元素的个数可以显示的或隐式的指定
观察下面两个数组,思考两个问题:① a[2],a[3],a[4] 的值是多少? ② b包含了多少个元素?
【数组的初始化】
1 #include <stdio.h> 2 3 int main() 4 { 5 int a[5] = {1, 2}; // 编译器将未初始化的元素初始化为0 6 int b[] = {1, 2}; // 数组未指定大小 ==> 编译器根据数组初始化的情况计算其大小(占用的空间最小) 7 8 printf("a[2] = %d ", a[2]); // 0 9 printf("a[3] = %d ", a[3]); // 0 10 printf("a[4] = %d ", a[4]); // 0 11 12 // sizeof(数组名) ==> 计算数组的大小 13 printf("sizeof(a) = %zu ", sizeof(a)); // 20 14 printf("sizeof(b) = %zu ", sizeof(b)); // 8 15 16 printf("count for a: %zu ", sizeof(a)/sizeof(a[0])); // 5 17 printf("count for b: %zu ", sizeof(b)/sizeof(b[0])); // 2 18 19 return 0; 20 }
3. 数组地址与数组名
(1)数组名代表数组首元素的地址
(2)数组的地址需要对数组名使用取地址符 & 才能得到
(3)数组首元素的地址值与数组的地址值相同,但是数组首元素的地址与数组的地址是两个不同的概念。
我们通常所说的地址包括两个方面的概念:起始地址 和 所占用内存空间的大小。数组名仅仅对应数组一个元素那么大的内存,而数组的地址对应整个数组所占用的内存空间。
【数组名和数组地址】
1 #include <stdio.h> 2 3 int main() 4 { 5 int a[5] = {0}; 6 7 printf("a = %p ", a); // 0x7ffc7425dbb0 8 printf("&a = %p ", &a); // 0x7ffc7425dbb0 9 printf("&a[0] = %p ", &a[0]); // 0x7ffc7425dbb0 10 11 return 0; 12 }
4. 数组名的盲点
(1)数组名可以看作一个指针常量;注意这里只是说"可以看作",并非是真正的指针常量
(2)数组名"指向"的是内存中数组首元素的起始位置
(3)数组名不包含数组的长度信息
(4)在表达式中数组名只能作为右值使用
(5)只有在下列场合中数组名不能看作常量指针
- 数组名作为作为 sizeof 操作符的参数,表示整个数组的大小
- 数组名作为 & 运算符的参数,表示整个数组的地址
【数组和指针并不相同】
1 #include <stdio.h> 2 3 int main(){ 4 5 int a[5] = {0}; 6 int b[2]; 7 int* p = NULL; 8 9 p = a; 10 11 printf("a = %p ", a); // 0x7ffe40054a70, 数组a首元素的地址 12 printf("p = %p ", p); // 0x7ffe40054a70 13 printf("&p = %p ", &p); // 指针p的地址, 0x7ffe40054a68 14 15 printf("sizeof(a) = %zu ", sizeof(a)); // 数组a的大小, 20 16 printf("sizeof(p) = %zu ", sizeof(p)); // 指针的大小为8(64位系统) 17 18 printf(" "); 19 20 p = b; 21 22 printf("b = %p ", b); // 0x7ffe40054a60, 数组b首元素的地址 23 printf("p = %p ", p); // 0x7ffe40054a60 24 printf("&p = %p ", &p); // 指针p的地址, 0x7ffe40054a68 25 26 printf("sizeof(b) = %zu ", sizeof(b)); //数组的大小, 8 27 printf("sizeof(p) = %zu ", sizeof(p)); //指针的大小为8(64位系统) 28 29 // a = b; // compile error, 数组名不能作为左值 30 // error: incompatible types when assigning to type ‘int[5]’ from type ‘int *’ 31 32 return 0; 33 }