本人在看这章的该习题时,也曾被搞糊涂过,其实刚开始还是不要看它的解释更好,多加一些打印语句,自然就知道各个变量的地址和对应的值了。
原题如下:
struct S
{
int i;
int* p;
};
S s;
int* p = &s.i;
p[0] = 4;
p[1] = 3;
到这一步,我们定义了一个指针,并开辟了空间大小就是sizeof(struct )那么再通过数组下标来给各个内存单元(数组元素)赋值,当然也可以通过指针偏移量来赋值,这些在C语言指针那里讲得很清楚,两种方式不一样而已。
也就是此时, s.i = 4; s.p = 3; 注意,因为结构体的第二个成员是整型指针变量,这里我们将结构体里面的指针p的地址设为00000003;注意,不是指针的指向内容!
s.p = 3(p[1] = 3) 类似于 int* p = (int*)3; 只是我们这里是通过一个指针p来给成员赋值的 由于数组类型 本来就是int 所以不需要强制转换!
注意区别 char* p = “123”;
接下来,
s.p = p;
这里就是说白了,将结构体成员的p的内容(不是指向的内容),它保存的是一个地址,改为p的内容即&s.i. 这里要注意区分 对于一个指针变量 它本身的地址 和 变量的内容(也是一个地址)以及 该指针变量指向的一个变量(所谓的指向的内容)这三者关系。
指针给指针赋值 ,一般是给他 变量的内容(一个地址) ,不是它本身的地址 也不是 指针变量所指的内容!
也就是说现在 s.p中的内容是 结构体的首地址!
好了,那后面的
s.p[1] = 1; // 联系上下两句 有点类似于, int a [] = {1, 2, 3,4}; int * p = a; p[1] = 1;
也就是使得s.p = 00000001;
之后再去 用数组下标法 s.p[0] (其实就是00000001地址指向的内容) 该内容不一定能够被访问!也就是s.p[0]的内容
同样的,之后s.p[1]也是不可以访问的
更何况写 也就是s.p[0] = 2 ; 更是不可能了。
最后,要注意的是 第一句s.p[1] =1 ; 在此之前由于 s.p是有合法(可正常读写)地址的,所以可以读写;
读写一次之后,由于给了它s.p 一个无法读写的地址如00000001, 那么之后的所有数组下标访问 如s.p[0] s.p[1] 都是非法的。