以下内容为本人大学时的笔记,最近偶然翻到,所以发出来也算留一下备份,所以有些描述什么的可能不太准确,欢迎各位大神批评指正。
整理《C语言深度剖析》4.3.2 –a和&a的区别
下面是陈正冲老师的《C语言深度剖析》的内容:
上面这些是书中的内容,我个人感觉最难理解的是&a+1,陈正冲老师对&a+1的解释如下:
对指针进行加 1 操作,得到的是下一个元素的地址,而不是原有地址值直接加 1。所以,一个类型为 T 的指针的移动,以 sizeof(T) 为移动单位。 因此,对上题来说, a 是一个一维数组,数组中有 5 个元素; ptr 是一个 int 型的指针。
&a + 1: 取数组 a 的首地址,该地址的值加上 sizeof(a) 的值,即 &a + 5*sizeof(int),也就是下一个数组的首地址,显然当前指针已经越过了数组的界限。
下面我们自己拿编译器一步一步进行(所用编译器:codeblocks):
- 写好程序并且设置好断点
- Debug并调出watch窗口
-
这是初始状态,编译器已经给a分配完地址:0x61fee8,所以按照书中所说&a+1 = &a+ 5 * sizeof(int) = 0x61fee8 + 5 * sizeof(int) = 0x61fefc;(谢天谢地codeblocks没有书中VC++6.0的bug)
a+1 = &a + sizeof(int) = a+1 = 0x61fee8 + sizeof(int) = 0x61feec; -
Run to cursor
a是数组首元素地址,a+1就是数组第二个元素地址,*(a+1)就是数组第二个元素,为:2 -
Run to cursor
因为ptr所指向的对象就是&a+1指向的对象,即a[5],所以ptr-1指向的就是a[4],*(ptr-1)就是a[4],即:5。
以上就是我个人对这个程序的整理,下面附上我整理之后的程序:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a[5] = {1,2,3,4,5}; //这步执行完:&a = 0x61fee8
//&a+1 = 0x61fee8 + 5 * sizeof(int) = 0x61fefc
//a+1 = 0x61fee8 + sizeof(int) = 0x61feec
//*(a+1) = 2
//ptr是垃圾值
//*(ptr-1)是垃圾值
int * ptr = (int *)(&a + 1); //这步执行完:&a = 0x61fee8
//&a+1 = 0x61fee8 + 5 * sizeof(int) = 0x61fefc
//a+1 = 0x61fee8 + sizeof(int) = 0x61feec
//*(a+1) = 2
//ptr = &a+1 = 0x61fefc
//*(ptr-1) = 5
printf("%d %d\n", *(a+1), *(ptr-1));
return 0;
}