user-0 提问: 笔试的时候做的，发现编译无错，运行到最后一句时出错

回复:
user: user-1
content: 引用 7 楼 angel_su 的回复:s.p[1]=3把自己改了指向地址3，这个位置系统不让改的...++正解

user: user-2
content: 崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。

user: user-3
content: 引用 10 楼 z1179675084 的回复:这里没有数组越界，就是在那捣鼓地址里面内容，32位机下面，这个程序有问题，64位机并且是64位编译器的话不会有任何问题！ 怎么可能没问题？s.p[1]=3;这句执行之后s.p指向的地址为0x00000003，s.p[0]=4就相当于是对0x00000003这个地址进行操作，不出错才怪。

user: user-4
content: 引用 11 楼 yulitingfeng 的回复:gcc打印出地址： s.i的地址：1961422464 p的地址：1961422464,p[1]的地址1961422468 s.p的地址：1961422464,s.p[1]的地址：1961422468 s.i=4,s.p[0]=4 ,s.p[1]=3,p[0]=4,p[1]=3  #include <stdio.h> struct S { 	int i; 	int *p; }; int main() { 	struct S s; 	int *p=&s.i; 	p[0]=1; 	p[1]=2; 	s.p=p; 	s.p[1]=3; 	s.p[0]=4; 	printf("s.i的地址：%d\n",&s.i); 	printf("p的地址：%d,p[1]的地址%d\n",p,&p[1]); 	printf("s.p的地址：%d,s.p[1]的地址：%d\n",&(s.p[0]),&(s.p[1])); 	printf("s.i=%d,s.p[0]=%d ,s.p[1]=%d,p[0]=%d,p[1]=%d\n",s.i,s.p[0],s.p[1],p[0],p[1]); }s.i，s.p[0]，p[0]地址都是1961422464。 p[1]和s.p[1]地址相同。

user: user-4
content: gcc打印出地址： s.i的地址：1961422464 p的地址：1961422464,p[1]的地址1961422468 s.p的地址：1961422464,s.p[1]的地址：1961422468 s.i=4,s.p[0]=4 ,s.p[1]=3,p[0]=4,p[1]=3  #include <stdio.h> struct S { 	int i; 	int *p; }; int main() { 	struct S s; 	int *p=&s.i; 	p[0]=1; 	p[1]=2; 	s.p=p; 	s.p[1]=3; 	s.p[0]=4; 	printf("s.i的地址：%d\n",&s.i); 	printf("p的地址：%d,p[1]的地址%d\n",p,&p[1]); 	printf("s.p的地址：%d,s.p[1]的地址：%d\n",&(s.p[0]),&(s.p[1])); 	printf("s.i=%d,s.p[0]=%d ,s.p[1]=%d,p[0]=%d,p[1]=%d\n",s.i,s.p[0],s.p[1],p[0],p[1]); }

user: user-5
content: 引用 1 楼 turingo 的回复:p[1]访问越界了，结果难料，出错很正常。  [quote=引用 楼主 ggyanjiang 的回复:] #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; }[/quote] 这里没有数组越界，就是在那捣鼓地址里面内容，32位机下面，这个程序有问题，64位机并且是64位编译器的话不会有任何问题！

user: user-5
content: 这个不是数组越界。问题如下： s.p[1] = 3==> *(&s.i + 1) = 3也就是s.p = 3,故其作用也就是s.p[0] 指向内存地址为 3的地方，你可以printf("%d\n",&s.p[0]);看看结果肯定为3 s.p[0] = 4==>*((int *)3) = 4不用我说你也知道不行了吧！ 这个是32位下的效果，64位下指针占8位，结构体内部还涉及到数据对齐和这个有区别！如果不用别的手段，这个程序不会有任何问题！

user: user-6
content: #include <stdio.h>  struct S { 	int i; 	int *p; }; int main() { 	struct S s; 	int *p=&s.i;//p指向s.i 	p[0]=1;//s.i=0 	p[1]=2;//s.p=2 	s.p=p;//s.p指向s.i 	s.p[1]=3;//s.p[1] == s.p = 3 --!!注意这里     printf("aa"); 	s.p[0]=4;//这里要把内存地址为3的位置的值 赋为4..... }  这是我的分析，不知道对不对..

user: user-7
content: s.p[1]=3把自己改了指向地址3，这个位置系统不让改的...

user: user-8
content: 好乱。。。。。。。。。

user: user-9
content: 嗯，楼上讨论的内存大小和字节对齐是有道理的，上述问题产生的原因还是使用s.p进行了不合法的读写，关键还是s.p[1] = 3这一步覆盖了s.p。 与指针是64位的类似，如果#pragma pack(8)之类的话上述问题也不会出现了

user: user-10
content: s.p[0]取值还没错，s.p[1]肯定是越界了，如果s.p[0]在前，还是能打印出数据的。支持s.p[1]会发生什么。。 undefine。。

user: user-9
content: 貌似是这样子：  #include <stdio.h> struct S {     int i;     int *p; }; void main() {     struct S s;     int *p=&s.i;//p指向s.i，S结构体占用8个字节，现在*p = p[0] = s.i，由于结构体内存连续存放，则*(p+1) = p[1] = s.p     p[0]=1;     //由上知，现在s.i = 1     p[1]=2;	//由上知，现在s.p = 2（s.p这个指针现在指向地址为0x00000002这个不允许读写的内存块）     s.p=p;      //由上知，现在s.p = p = &s.i     s.p[1]=3;   //由上知，与p = &s.i时p[1] = s.p一样，现在是s.p = &s.i，则s.p[1] = s.p，从而现在s.p = 3， 		//即s.p这个指针现在指向地址为0x00000003这个不允许读写的内存块     printf("aa");     s.p[0]=4;	//s.p[0] = *s.p = *((int*)0x00000003) = 4，不合法写 }

user: user-11
content: 同意楼上的解释

user: user-12
content: 最后打印出s。p[1]地址是0x7，因为s。p[0]地址是0x3，加上4字节，所以是0x7

user: user-12
content: 所以最后一句s.p[0]就是从地址0x3后退4字节，这部分区域不可访问的导致报错。  这句话说错了，s.p[0]应该就是0x3

user: user-12
content: 11楼说的有点道理外，其他全是扯淡，经实验证明：  前面流程就不多说了，从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后退4字节，这部分区域不可访问的导致报错。  lz的另一种情况，假如s。p[0]放在s.p[1]的前面赋值，因为s。p[0]指向是s.i的地址，所以赋值没有错误，s。p[1]指向是s.p指针变量的地址，所以给s.p指针变量赋值是没有错的，就是改变s。p指向而已。   以上都是经过程序验证得出的，没有错误，lz自己可以读出s。p变量本身的地址和内容就知道了。谢谢

user: user-5
content: 引用 18 楼 L812234929 的回复:[quote=引用 17 楼 z1179675084 的回复:] 你认真读一下我9楼的回复，你说的这个我已经在9楼回答过了，我说的没问题是指64位机，64位编译器下面，如果就这样写绝对不会有问题，不信你按我的条件编译试试，或者我给你画个图你就明白了。 我好像记得标准里面int型在64位机器下面也战了8个字节吧，当然我这没有64为机器，我也没法测试。如果你用64位机器测试过，那么我错了。[/quote] 呵呵，我是个学生，回答问题不多，但是所有我回答的，都是认真思考验证过的。

user: user-3
content: 引用 17 楼 z1179675084 的回复:你认真读一下我9楼的回复，你说的这个我已经在9楼回答过了，我说的没问题是指64位机，64位编译器下面，如果就这样写绝对不会有问题，不信你按我的条件编译试试，或者我给你画个图你就明白了。 我好像记得标准里面int型在64位机器下面也战了8个字节吧，当然我这没有64为机器，我也没法测试。如果你用64位机器测试过，那么我错了。

user: user-5
content: 引用 13 楼 L812234929 的回复:[quote=引用 10 楼 z1179675084 的回复:]  这里没有数组越界，就是在那捣鼓地址里面内容，32位机下面，这个程序有问题，64位机并且是64位编译器的话不会有任何问题！ 怎么可能没问题？s.p[1]=3;这句执行之后s.p指向的地址为0x00000003，s.p[0]=4就相当于是对0x00000003这个地址进行操作，不出错才怪。[/quote] 你认真读一下我9楼的回复，你说的这个我已经在9楼回答过了，我说的没问题是指64位机，64位编译器下面，如果就这样写绝对不会有问题，不信你按我的条件编译试试，或者我给你画个图你就明白了。