大神是如何玩C语言的!

  我在酷壳上看到一篇文章,C语言结构体里的成员数组和指针,看得感受让我真是佩服地五体投地啊。皓哥虽然说谦称本身不是高手啥的,可是写出这样的文章来,真是让我感受本身的水平真是渣渣!我看完了感受有点小激动,也想本身讲讲,试试,看看能不能讲清楚那个微博中所叙述的的问题,绝对没有抄袭的意思。因为个人水平实在有限,写的可能很糟糕,还请各位见谅!html

   

  OK,废话少说,先来讲说一下问题,有这么一段代码,shell

 1 #include<stdio.h>
 2 struct str{
 3     int len;
 4     char s[0];
 5 };
 6 
 7 struct foo {
 8     struct str *a;
 9 };
10 
11 int main(int argc, char** argv) {
12     struct foo f={0};
13     if (f.a->s) {
14         printf( f.a->s);
15     }
16     return 0;
17 }

  这个程序会在哪一行挂掉呢?我用的是gcc,我这里是在第14行挂掉的。为何呢?为何那个if语句那里不挂掉,而是在printf语句这里挂掉呢?数组

  这个咱们首先得分析变量是啥?变量是啥,其实就是内存区域的别名!而结构体类型的变量,其实就是一大块内存区,而后结构体变量名指向的是这块内存区的起始地址,而后根据变量的类型来不断向后推出其余变量。好比上面那个str结构体。其实就是一块4字节内存用来存放int变量len,而后后面的字节用来存放字符数组s。咱们能够经过gdb打印出他们的地址,以下图所示:函数

  

  这里结构体变量t和它的第一个成员len的地址都是0xbffff184,而它的s成员的地址就是t的地址+4也就是0xbffff188。OK,经过这样的叙述不知道你们能不能理解,其实结构体中每一个成员的变量的地址其实就是结构体变量的地址加上相对偏移。好比上面例子中s的地址就是t的地址加上4个字节(表明int变量)。spa

  知道了这个概念,咱们来分析一下这段程序。指针

  

  首先从主函数开始,创建了一个f变量,里面有一个成员是指针a,而后指针a里面存放的地址被初始化为0。而后在if语句中使用的是f.a->s,它就是找到一个地址,就是s变量的地址,寻找的方式就是先找到结构体变量指针a中存放的地址,而后再对这个地址+4,而后找到这个地址以后并无去访问这个地址所表明的内存空间,因此程序没有报错。而在print语句中呢,也是先找到这个地址,而后去访问这个地址所表明的内存空间,试图在这个空间中寻找一串字符串并输出出来。因为a中咱们已经初始化为0,因此访问的内存空间就是0x4的空间,因此程序就会挂掉了!^ o ^code

相关文章
相关标签/搜索