我在正在学习C语言,对于数组名和数组名取地址的区别,我感到有点迷惑。我想尝试用自己的理解去剖析理解。
- 首先我们先上程序
接下来我们看一下结果:(本结果是运行环境是win10用codeblocks)
通过上面的运行结果可以看出
- arr 和&arr和&arr[0]的地址是一样的,看起来arr和&arr并没有什么不同
- arr 和 arr+1的地址相差sizeof(int)4个字节,这是指针的步长这并不难理解
- 通过上图我们可以看到&arr[4]=FEFC(为了简洁省略前面的值,方便观察) &arr+1=FF00
- &arr[4]代表第5个元素的首地址,那么这个数组末尾的地址就是FEFC+4=FF00
第5个元素的末尾地址刚好是&arr+1的值,&arr+1就是直接指向了数组的最后,也就是说&arr+1刚好跨过=元素个数*sizeof(int),
这里(元素个数是5)*(sizeof(int)=4)=20=0x14
arr的首地址是 FEEC +0X14=FF00
- 到这里我们似乎得出结论arr+1是在数组内进行移动,每次移动大小是元素类型的大小,数组名个数组arr[0]是等价的。
- 如果们先进行&arr+1操作,那么就是每次移动大小是整个数组的大小也就是sizeof(arr);
- 我们到这里应该似乎明白了这两个的区别:若是对数组名进行取地址(&)操作,每次移动就是整个数组的大小,移动后指向数组末尾地址。;若不对数组名取地址那么移动就是sizeof(类型);
- 他俩的移动长度不一样那么类型肯定也就不一样,这是从目前结果合理的推断。一个是指向数组末端,一个是数组首端,同一数组内指针地址按道理是可以相减的,但是当我运行下面这个打印操作的时候编译器进行了报错。
报错:
E:Codeblocklearntestmain.c|18|error: invalid operands to binary - (have 'int (*)[5]' and 'int *')|
这个错误告诉我们-号两边的类型是不一样的,这似乎就是这个问题的根源
&arr+1类型是int(*)[5]; &arr的类型是int*类型
我们知道()的优先级是最高,我们要把括号里的内容(*p)看成一个整体,其实就是一个数组,只不过这个数组的地址给了p,也就是p指向这个数组。所以这是定义”数组的指针“
int * p可以写成int *(p[ ]),如果把p[ ]看成一个整体,则可以发现其实就是定义一个指针,这个指针指向某个地方,再看个体,其实就是一个全是指针的数组。所以这是定义”指针数组“
到这里我们可以得出结论 &arr +1 和arr 归根到底是类型的不同,前者是数组的指针后者是指针的数组。