从cdsn上看到这么一篇程序:
#include <stdio.h>
struct S
{
int i;
int *p;
};
void main()
{
struct S s;
int *p=&s.i;
p[0]=1;
p[1]=2;
s.p=p;
s.p[1]=3;
pritnf("aa");
s.p[0]=4;
}
以下是自己加的打印信息:
1 #include <stdio.h>
2 struct S
3 {
4 int i;
5 int *p;
6 };
7 void main()
8 {
9 struct S s;
10 int *p=&s.i;
11 int q;
12 p[0]=1;
13 printf("p[0]=%p, s.i=%p s.p=%p\n", &p[0], &s.i,&s.p);
14 p[1]=2;
15 printf("p1=%d, %p\n", p[1],&p[1]);
16 s.p=p;
17 q=3;
18 printf("aabb====s.p=%p,,%d, q=%p\n", s.p, &q);
19 s.p[1]=3;
20 int *pp = &s.p;
21 printf("s.p=%d, s.p1=%p, q=%p\n", *(pp), &s.p[1], &q);
22 s.p[1]=4;
23 printf("s.p0=%p, %d, s.p1=%p, %d\n", &(s.p[0]), s.p[0], &s.p[1],s.p[1]);
24 }
打印的结果:
p[0]=0xbfb4062c, s.i=0xbfb4062c s.p=0xbfb40630
p1=2, 0xbfb40630
aabb====s.p=0xbfb4062c,,-1078720972, q=0xbfb40630
s.p=3, s.p1=0x7, q=0xbfb40634
Segmentation fault (core dumped)
程序的本身是很简单的,但是往往会绕晕掉,以下是我详细的解释:
前面流程就不多说了,从s.p开始吧,s.p=p,也就是s.i的地址,就是s.p指针变量里面存的是s.i的地址,s.p[1]所指向的地址其实也就是结构体定义s.p变量的地址,也是s。p指针变量本身的地址,不要搞混,(一个是指针所指向也就是所保存的地址,一个是指针变量本身的地址,注意两者的区别),当s。p[1]=3时候,也是往s.p指针变量里面保存3这个数值,这样就好理解了,那么s。p指针变量所指向的地址就是0x3,所以最后一句s.p[0]是地址0x3,s.p[1]地址是0x7, 跟打印出来的效果是一样的,这部分区域不可访问的导致报错。
另一种情况,假如s。p[0]放在s.p[1]的前面赋值,因为s。p[0]指向是s.i的地址,所以赋值没有错误,s。p[1]指向是s.p指针变量的地址,所以给s.p指针变量赋值是没有错的,就是改变s。p指向而已。