Chinaunix首页 | 论坛 | 博客
  • 博客访问: 60483
  • 博文数量: 8
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 82
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-04 17:00
文章分类

全部博文(8)

文章存档

2016年(5)

2015年(3)

我的朋友

分类: C/C++

2016-03-05 15:53:00

转载请注明出处:http://blog.chinaunix.net/uid-30008524-id-5663353.html

        C语言里面有很多奇怪的东西,数组名就是其中一个,对于数组名的概念,网上众说纷纭,有人说数组名是一个指针常量,有人说数组名是一个地址常量,有人说数组名不是指针,但会退化成指针,等等。为什么数组名这么迷惑众人呢,原因很简单,它在不同场合表现不一样,有时候像指针,有时候像地址,演起来一套一套的,十分入戏,不少人都被它迷惑。相信每一个C/C++程序员都会有一个搞清楚数组名的过程。

关于数组名的概念,先总结几点:
1.数组名不是指针,也不是地址,它是一个名字,对应着一块数组大小的内存。
2.当遇到sizeof和&操作符的时候,它表现的就是它原来的面貌,代表一块数组大小的内存。
3.其它时候,它表现的像一个指向数组首元素地址的指针常量。

我们写个小程序,然后用gdb验证一下上面的总结。

点击(此处)折叠或打开

  1. #include "stdio.h"
  2. void func(int* shuzu,int len)
  3. {
  4.     for(int i=0;i<len;i++)
  5.     {
  6.         printf("%d ",*(shuzu+i));
  7.     }
  8.     printf("\n");
  9. }
  10. int main()
  11. {
  12.     int A[3] = {1,2,3};
  13.     int* B = A;
  14.     func(A,3);
  15.     func(B,3);
  16.     return 0;
  17. }
在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或&的时候,数组名变回自己:一个名字,对应着一块内存。

阅读(1679) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

xiaolo20082016-03-10 15:53:45

不错, 学习了!