一个关于结构体中数组访问范围的题目,一开始做错了,现在记录下来,分享一下:

  1. #include <stdio.h>  
  2.  
  3. struct S {  
  4. int i[2];  
  5. char str;  
  6. int *p;  
  7. };  
  8.  
  9. int main(int argc, char* argv[])  
  10. {  
  11.     /////////////////////////////////  
  12.     //本部分关于指针运算的先后问题  
  13.     int arr[]={6,7,8,9,10};  
  14.     int  *ptr=arr;  
  15.     (*ptr++)+=123;    
  16.     ptr++;  
  17.     printf("%d\n",*ptr);  
  18.     printf("%d.%d\n",*ptr,*(++ptr));  
  19.     /////////////////////////////////////  
  20.     //////////////////////////////////////  
  21.     //本部分是关于结构体中数组的访问范围  
  22.     struct S s;   
  23.     int *p =s.i;  
  24.     printf("%d",sizeof(S));   
  25.     p[0]=4;   
  26.     p[1]=3;  
  27.     p[2]=4;   
  28.     s.p=p;  
  29.     s.p[0] = 0;  
  30.     s.p[1] = 1;  
  31.     s.p[2] = 2;  
  32.     for(int k=0; k<3; ++k)  
  33.     {  
  34.      printf("\n%d",s.p[k]);  
  35.     }  
  36.     s.p[3] = 3;  
  37.     s.p[4] = 4;  
  38.     ///////////////////////////////////////  
  39.     return 0;  

程序的第一部分输出的结果是:

  1. 8  
  2. 9.9 

可以看出第二个printf语句的和第一个语句的输出不同了,因为第二个输出的计算的顺序是从右向左,所以ptr是++运算后的地址。

程序第二部分输出结果是:崩溃了,哈哈~~猜猜在哪个地方崩溃了

 

答案是:第37行s.p[4]=4;崩溃了,注释掉第37行,输出结果如下:

  1. 16  
  2. 0  
  3. 1  

为什么到第37行崩溃了呢?

这里主要是因为结构体的大小,我们在指针是结构体中数组 i 的地址,从此地址开始到结构体结束空间大小只有16,所以我们能访问4个int型的数据,故到s.p[4]时崩溃了。

如果我们把s.p[3]=3;写到循环前面,会在哪个地方崩溃呢?

答案是:在for循环中的第一个printf语句处崩溃,因为我们把指针的地址改了,哈哈~~s.p[3]实际上是结构体中指针p的地址。