文章目录
1 数组的概念
- 数组是相同类型的变量的有序集合
2 数组的大小
- 数组在一片连续的内存空间中存储元素
- 数组元素的个数可以显示或隐式指定
如下定义两个数组 a 和 b
有两个问题?
- a[2],a[3],a[4] 的值是多少?
- b 包含了多少个元素?
下面我们就来实际操作一下:
// 27-1.c
#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) = %ld\n", sizeof(a));
printf("sizeof(b) = %ld\n", sizeof(b));
printf("count for a: %ld\n", sizeof(a)/sizeof(int));
printf("count for b: %ld\n", sizeof(b)/sizeof(int));
return 0;
}
$ gcc 27-1.c -o 27-1
$ ./27-1
a[2] = 0
a[3] = 0
a[4] = 0
sizeof(a) = 20
sizeof(b) = 8
count for a: 5
count for b: 2
- 可以看到数组 a 只初始化了前两个元素,后面三个元素没有初始化,自动初始化为 0。
- 数组 a 的长度为 20 字节,里面保存了 5 个 int 型的数据类型,数组 b 元素的个数被隐式初始化,根据元素的个数确定数组长度,所以数组 b 长度为 2,里面有两个 int 型的变量。
- 求解数组长度的方法:数组长度除以单个元素长度 sizeof(a)/sizeof(a[0])
- 如果想将数组所有元素都初始化为 0,可以这么写: int a = { 0 }; 也就是第一个元素初始化为 0,后面的默认初始化,也是 0
3 数组地址与数组名
- 数组名代表数组首元素的地址
- 数组的地址需要用取地址符 & 才能得到
- 数组首元素的地址值与数组的地址值相同
- 数组首元素的地址与数组的地址是两个不同的概念
//27-2.c
#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;
}
$ gcc 27-2.c -o 27-2
$ ./27-2
a = 0x7ffc98bcb2c0
&a = 0x7ffc98bcb2c0
&a[0] = 0x7ffc98bcb2c0
- 数组名就是数组首元素的地址,所以 a 和 &a[0] 是一样的。
- 数组的地址指的是整个数组的地址,数值上等于数组首元素的地址,但是含义是不一样的。数组首元素的地址表示第一个元素的地址,一共只有一个元素,数组的地址表示整个数组的地址,一共有 5 个元素。这就好比是你家住小区第一户,你家的编号和小区编号一样,但是不能说整个小区都是你家。
4 数组名的盲点
- 数组名可以看做一个常量指针
- 数组名“指向”的是内存中数组首元素的起始位置
- 数组名不包含数组的长度信息
- 在表达式中数组名只能作为右值使用
- 只有在下列场合中数组名不能被看作常量指针
- 数组名作为 sizeof 操作符的参数
- 数组名作为 & 运算符的参数
为了更好的区别指针与数组,下面看个例子
// 27-3.c
#include<stdio.h>
int main()
{
int a[5] = {0};
int b[1];
int* p = NULL;
p = a;
printf("a = %p\n", a); // 数组的地址
printf("p = %p\n", p); // 指针p的内容,指针p指向数组a首元素,所以p是第一个元素的地址
printf("&p = %p\n", &p); // 指针也是变量,也有地址
printf("sizeof(a) = %ld\n", sizeof(a)); // 数组的大小
printf("sizeof(p) = %ld\n", sizeof(p)); // 指针的大小
printf("\n");
p = b;
printf("b = %p\n", b);
printf("p = %p\n", p);
printf("&p = %p\n", &p);
printf("sizeof(b) = %ld\n", sizeof(b));
printf("sizeof(p) = %ld\n", sizeof(p));
//b = a; // error
return 0;
}
$ gcc 27-3.c -o 27-3
$ ./27-3
a = 0x7ffce8616f60
p = 0x7ffce8616f60
&p = 0x7ffce8616f50
sizeof(a) = 20
sizeof(p) = 8
b = 0x7ffce8616f5c
p = 0x7ffce8616f5c
&p = 0x7ffce8616f50
sizeof(b) = 4
sizeof(p) = 8
不管数组大小如何变化,指针永远是 8 个字节(64位系统),指针与数组完全不是一概念
5 小结
1、数组是一片连续的内存空间
2、数组的地址和数组首元素的地址意义不同
3、数组名在大多数情况下被当作常量指针处理
4、数组名其实并不是指针,不能将其等同于指针