最近看了好多,也編了好多C語言的浩強哥書後的題,總覺的很不爽,真的真的好懷念linux驅動的代碼,好懷念那下劃線,那結構體,雖然自己還很菜。
同時看了一遍陳正沖老師的C語言深度剖析,收益很多,又把唐老師的視頻復習了一部分,感覺收獲更多。
這階段一直想寫一篇博客,其實有好多東西,先寫一下C語言中的內存對齊吧。
大家都知道,在C語言中定義一個變量,char是占用一個字節的,int占用四個字節,float占用四個字節,double占用八個字節,short占用兩個字節,long int占用四個字節,long long神馬的是64位機器用的,暫時不討論。
上面說基本的數據類型所占用的字節數,程序的測試咱們printf一下(由於是菜鳥,所以咱們就不玩F8,F9的問題了)。程序如下:
include<stdio.h> int main(void) { char a; short b; int c; long int d; double e; float f; printf ("%d,%d,%d,%d,%d,%d\n",sizeof (a),sizeof (b),sizeof (c),sizeof (d),sizeof (e),sizeof (f)); return 1; } #include<stdio.h> int main(void) { char a; short b; int c; long int d; double e; float f; printf ("%d,%d,%d,%d,%d,%d\n",sizeof (a),sizeof (b),sizeof (c),sizeof (d),sizeof (e),sizeof (f)); return 1; }
好了,我們可以知道這些數據類型占用的字節空間了,那麼現在提出一個問題。
struct student { short s; long b; }stu; struct student { short s; long b; }stu;
當我們以4字節的方式編譯的時候,請問printf("%d",sizeof(stu));
我一直都認為這個打印的值是6,因為很明顯嘛,short是兩個字節的,long是四個字節的,所以打印出來的大小就是6個字節嘛。那好,請在VC下編譯測試一下吧。
結果出來的是8!!!
出乎意料了,這就是內存對齊。
內存對齊的意義在於:處理器是以規定的字節數進行讀取字節數的,我們編譯的是以4字節讀取字節數,這就是問題的所在。而且,讀取的塊的大小必須是2的N次冪。
下面我們解釋一下,上面那個結構體打印出來的大小是8的原因。
原因:short類型占用兩個字節,四個字節是一塊的情況下,那麼當一個short類型占用兩個字節以後還剩下兩個字節,但是接下來我們要存儲的是四個字節的long型,如果按照打印六的話,那麼我們的處理的取值將會蒙圈,所以實際上編譯器把這兩個數據分配的空間是short占用兩個字節後空出兩個字節的位置,這樣完成了一個四個字節的塊,然後接下來的一個long型占用四個字節,這樣完成了兩個塊,所以我們打印出來的是8 。空說估計一會自己都暈了,所以畫個圖:
同時還要說一下內存的對齊的規則:
①必須要按照編譯器指定的字節數進行讀取,同時還要考慮怎麼樣才可以使編譯器讀取數據最快捷。
②另外最後占用的字節數必須是整個結構體中字節數最大數據類型的整數倍。
還有一些其他規則,下面再進行介紹。
一個結構體的問題差不多了吧?那麼再看一個:
include <stdio.h> struct student { short s; long b; }stu1; struct teacher { char c; struct student stu1; double e; }stu2; int main() { printf("%d,%d\n",sizeof(stu1),sizeof(stu2)); } #include <stdio.h> struct student { short s; long b; }stu1; struct teacher { char c; struct student stu1; double e; }stu2; int main() { printf("%d,%d\n",sizeof(stu1),sizeof(stu2));
}咱們還是打印,那麼打印出來的是多少呢?
這裡說個插曲,在VC中默認的是8位編譯,這個時候打印出來的是8和24,在linux下的GCC編譯,打印出來的是8和20 。一直認為VC是4位編譯,所以走了一些彎路,後來使用宏條件判斷才知道VC是4位編譯。下面分別說一下這種結構體嵌套結構體的內存對齊。
上面說的是4位的,那麼這裡我們還說繼續先說4位的。
打印20的原因:
先說一下第二個結構體的第一個成員char,占用的是一個字節。第一個結構體的第一個成員short占用兩個字節,第二個成員占用四個字節。好了,暫停一下,我這個時候我就疑惑了,為什麼char和short不在一個四字節的塊中呢,這樣編譯器也可以按照四字節進行很快速的讀取啊?但是這個時候應該考慮的是,第一個結構體已經被編譯器分配好了一個完整的空間,所以這個short是不可以並到第一個結構體中的。回到主題,第一個char單獨占用一個字節的四字節的塊,第一個結構體占用連個四字節的塊,double為8字節,占用兩個四字節的塊,最後占用的是五個四字節的塊。所以打印20 。
上圖:
下面說一下當按照8字節進行編譯的時候打印出24的原因。(雖然是8字節進行編譯的,但是讀取的還是按照四個字節進行讀取的,這樣的話前面說的原則仍然成立。)
原因如下:第一個char占用了一個字節,但是按照8字節存儲,按照4字節讀取,所以char占用了8字節前面的4字節,後面的四個字節被short占用,這樣也完成了處理器最快速度讀取並且沒有破壞第一個結構體的整體性。剩下的一個一個long占用了一個四字節,我的同學說這個八字節的塊要空出來四個,因為不可以把後來的double拆開,但是我認為這麼解釋不是很合理,我也不清楚原因是什麼,所以暫時擱置。
上圖:
先說這麼多吧,這裡面還有一些小東西,太晚了,各位建軍節快樂吧,我明天還要繼續我苦逼的實訓道路。