1.数组的基本概念
- 数组是相同类型的变量的有序集合
- 数组当中的元素没有名字,我们只能通过数组名和下标来访问数组中的元素。数组名a代表的是这5个存储空间的集合。代表的是这一段内存。
- 数组在—片连续的内存空间中存储元素,数组元素的个数可以显示或隐式指定
#include <stdio.h>
int main()
{
int a[5] = { 1, 2 }; // 显示指定
int b[] = { 1, 2 }; // 隐式指定
printf("a[2] = %d\n", a[2]);
printf("a[3] = %d\n", a[3]);
printf("a[4] = %d\n", a[4]);
printf("sizeof(a) = %d\n", sizeof(a));
printf("sizeof(b) = %d\n", sizeof(b));
printf("count for a: %d\n", sizeof(a) / sizeof(int));
printf("count for b: %d\n", sizeof(b) / sizeof(int));
return 0;
}
- 运行结果:
- 当我们指定数组中的一部分元素之后,其他的元素就会被初始化为0,我们可以利用这个特性来讲数组全部初始化为0。做法为int a[5] = {0}; 我们将第一个元素初始化为0,其他的元素由编译器默认初始化为0。
2. 数组的地址与数组名
- 数组名代表数组首元素的地址
- 数组的地址需要用取地址符&才能得到
- 数组首元素的地址值与数组的地址值相同
- 数组首元素的地址与数组的地址是两个不同的概念
#include <stdio.h>
int main()
{
int a[5] = { 0 };
printf("a = %p\n", a);
printf("&a = %p\n", &a);
printf("&a[0] = %p\n", &a[0]);
return 0;
}
- 运行结果:
- a:数组名,&a: 数组的地址,&a[0]:数组首元素地址
- 数组的地址包含两层含义:一是数组的起始地址,二是所占用的内存的长度(多少个字节)。
- 数组首元素地址也包含两层含义:一是第一个元素的起始地址,二是第一个元素所占内存的长度。
3.数组名与指针
- 数组名可以看做—个指针常量(int* const p)
- 数组名“指向”的是内存中数组首元素的起始位置
- 数组名不包含数组的长度信息
- 在表达式中数组名只能作为右值使用
- 只有在下列场合中数组名不能看做指针常量
- 数组名作为sizeof操作符的参数
- 数组名作为&运算符的参数
#include<stdio.h>
int main()
{
int a[5] = { 0 };
int b[2];
int *p = NULL;
p = a;
printf("a = %p\n", a);
printf("p = %p\n", p);
printf("&p = %p\n", &p);
printf("sizeof(a) = %d\n", sizeof(a));
printf("sizeof(p) = %d\n", sizeof(p));
p = b;
printf("b = %p\n", b);
printf("p = %p\n", p);
printf("&p = %p\n", &p);
printf("sizeof(b) = %d\n", sizeof(b));
printf("sizeof(p) = %d\n", sizeof(p));
//b = a; //error: assignment to expression with array type
return 0;
}
- 运行结果:
- sizeof对指针和数组名操作时,结果是不一样的。
- 数组名绝对不等于指针,而且不是指针,只是很多情况可以看成指针常量处理。
4.小结
- 数组是一片连续的内存空间;
- 数组的地址和数组首元素的地址意义不同;
- 数组名在大多数情况下被当成指针常量处理;
- 数组名其实并不是指针,不能将其等同于指针。