关于数组名的概念,先总结几点:
1.数组名不是指针,也不是地址,它是一个名字,对应着一块数组大小的内存。
2.当遇到sizeof和&操作符的时候,它表现的就是它原来的面貌,代表一块数组大小的内存。
3.其它时候,它表现的像一个指向数组首元素地址的指针常量。
我们写个小程序,然后用gdb验证一下上面的总结。
-
#include "stdio.h"
-
void func(int* shuzu,int len)
-
{
-
for(int i=0;i<len;i++)
-
{
-
printf("%d ",*(shuzu+i));
-
}
-
printf("\n");
-
}
-
int main()
-
{
-
int A[3] = {1,2,3};
-
int* B = A;
-
func(A,3);
-
func(B,3);
-
return 0;
-
}
在main函数入口处设置断点,然后run

程序遇到断点,暂停了运行,我们来查看一下A和B的值

可以看到数组A里面填充着三个随机数,B也指向一个随机地址(所以指针一定要初始化,让它指向NULL或者一个确定的地址,否则后果严重)。
我们next几步,运行到int* B=A,再查看

A已经初始化成功,B指向了A的首元素地址0xbffff610
看看size

A是数组名,遇到sizeof就原形毕露,所以sizeof(A) = 12字节,而B是指针,只占用4个字节,所以sizeof(B) = 4。从这里就可以看出数组名不是指针。
再看看数组名A遇到“&”操作符会怎么样:
&A的地址是0xbffff610,&A+1的地址是0xbffff61c,相差12个字节,而不是4个。因为A遇到“&”也恢复了总结1中定义的样子,对应着一个12字节的内存块。
用ptype看它们的类型

step一步,进入func(A,3)

有人说数组名A传递进来之后退化成普通指针了,在函数内部可以像普通指针那样用它。但在上图可以看到,形参shuzu被赋值0xbffff610(A的首元素地址)。也就是A只是把首地址交给了shuzu,并没有进入函数内部,也没有退化成指针,交接完之后就离开了。函数内部操作都是对shuzu的操作,而不是对A。
func定义的时候,形参定义成int*类型,但传数组名A进来不会有任何报错,说明数组名平时表现的像一个指针,而且是一个指针常量,不能左值操作。
最后的运算结果,传指针和传数组名得到的结果是一样的。

也就是说,当没有遇到sizeof和&的时候,数组名表现的像一个指针常量,当遇到sizeof或&的时候,数组名变回自己:一个名字,对应着一块内存。
阅读(1699) | 评论(1) | 转发(0) |