大神是如何玩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