首先我们来看一段程序:
#include <stdio.h>
int main(int argc,char *argv[])
{
int numbers[5] = {1, 2, 3, 4, 5};
printf("&numbers: %p\n", &numbers);
printf("&numbers+1: %p\n", &numbers+1);
printf("numbers: %p\n", numbers);
printf("numbers+1 :%p\n", numbers+1);
int *p = numbers;
printf("sizeof(&numbers): %d\n", sizeof(&numbers));
printf("sizeof(numbers): %d\n", sizeof(numbers));
printf("sizeof(*numbers): %d\n", sizeof(*numbers));
printf("sizeof(*p): %d\n", sizeof(*p));
printf("sizeof(p): %d\n", sizeof(p));
return 0;
}
这段程序的输出结果:
下面来分析输出结果:
我们先来分析 numbers 和 &numbers:
1.首先,用%p将 numbers 和 &numbers打印出来,它们的地址自然都是一样的,因为它们都等于数组的首地址。 但是,我们将它们的地址+1后打印出来,结果却大相径庭。那么,这是为什么呢?
其实,虽然 numbers 和 &numbers 都代表数组首地址, 但是它们所指向元素的类型却是不一样的。&numbers 所指向的类型是int [5] 型的数组,占据5*sizeof(int) = 20 个字节。而numbers 指向的类型是 numbers[0] 这种 int 类型数组的成员,注意,是成员不是整个数组!它的 大小只有 sizeof(int) = 4 个字节。所以它们的地址+1后, 与原地址相差分别为20和4。
2.接下来,我用 sizeof 对 &numbers, numbers, *numbers 求长度。结果分别为8,20,4。经过分析, &numbers 是一个地址,在64位下经 sizeof 输出为8, 这个并无疑问。
但是,sizeof(numbers) 结果等于20, 却与上面的分析相悖,其实这里有个很重要的点就是, 数字名并不是指针! 虽然数组名可以在很多时候作为指针来使用,如上文中所说
numbers 指向类型为 int的数组成员, 但是在用于 sizeof 时, numbers 是作为它的本身数组名来使用, 它指向的实体其实是一种数据结构,这个结构就是数组。所以 numbers
进行求长度操作,等价于对数组求长度,结果自然是20。而后面对 sizeof(*numbers) 等价于 sizeof(*(numbers+0)),即对 numbers[0] 求长度,它的结果是sizeof(int) = 4。
总而言之,我们一定要认识到,数组名不是指针!虽然数组名很多时候可以作为指针来使用(如在上文1中),但要在进行 sizeof 这种操作时, 数组名本来的意义就体现了,
它所代表的就是数组这种数据结构。
3.另外还有一种错误的认识,就是想要求数组长度时,千万不能对指向数组的指针求长度!
程序中指针变量p指向数组首地址, sizeof(*p) 等价于 sizeof(numbers[0],结果为 sizeof(int) =4。
而 sizeof(p) 呢, p是一个指针变量,对一个指针变量求长度,更不能代表对数组求长度,它的结果在64位下就是一个地址的长度,为8个字节。