全攻略有點大放厥詞,嘩眾取寵了,其實是一些常見的問題罷了。但是自認為總結(jié)的還算全面一點吧,請大家多多賜教,我只是個初學(xué)者。

接下來主要討論四點:
一、不涉及位域的內(nèi)存對齊原則
二、涉及位域的內(nèi)存對其原則
三、成員變量含有結(jié)構(gòu)體的內(nèi)存對齊情況
四、要求內(nèi)存對齊的原因及優(yōu)點

引子:
 1#include <iostream>
 2using namespace std;
 3struct A
 4
 5    char m; 
 6    int n; 
 7}
;
 8int main ()
 9
10    A a; 
11    a.m=1;a.n=2;
12    printf("sizeof(A)=%d\nsizeof(A.m)=%d\nsizeof(A.n)=%d\n",sizeof(a),sizeof(a.m),sizeof(a.n)); 
13    return 0;
14}

預(yù)測輸出:
sizeof(A)=5
sizeof(A.m)=1
sizeof(A.n)=4
實際輸出:

分析:
也許該疑問了,sizeof(A.m)=1,sizeof(A.n)=4,sizeof(A)不是該1+4=5嗎,怎么是8呢?

這是因為程序員眼中的內(nèi)存與處理機處理內(nèi)存的不一致,請看下圖:
程序員通常認為內(nèi)存就是一些列簡單的字節(jié)數(shù)組,在C語言以及它的衍生語言中,char*被普遍認為代表一塊內(nèi)存區(qū)域,即使是Java也用byte[]來代表原始內(nèi)存如下圖所示:

處理機在對內(nèi)存進行存取操作時,卻不是以單個字節(jié)為單位來進行的,它通常是以2 、4、 8 、16大小的字節(jié)塊來進行的。我們稱處理器訪問內(nèi)存時一次存取的內(nèi)存大小為內(nèi)存訪問粒度”,如下圖所示:


可以看一下內(nèi)存中的情況,確實是8個字節(jié):


一、不涉及位域的內(nèi)存對齊原則
規(guī)則如下,然后來舉例說明:
1)對結(jié)構(gòu)的數(shù)據(jù)成員,第一個數(shù)據(jù)成員位于偏移為0的位置,以后每個數(shù)據(jù)成員的偏移量必須是MIN(#pragma pack()指定的數(shù),此數(shù)據(jù)成員的自身長度) 的倍數(shù),我們稱MIN(#pragma pack()指定的數(shù),此數(shù)據(jù)成員的自身長度) 為該結(jié)構(gòu)成員的對齊模數(shù)。
注:程序中通常是不指定#pragma pack()它的,默認值為8,從哪里可以看到呢,看下圖(發(fā)現(xiàn)用圖說話有時是直觀方便易懂……):


2)為結(jié)構(gòu)體的一個成員開辟空間之前,編譯器首先檢查預(yù)開辟空間的首地址相對于結(jié)構(gòu)體首地址的偏移是否是本成員的整數(shù)倍,若是,則存放本成員,反之,則在本成員和上一個成員之間填充一定的字節(jié)(填充字節(jié)為CC,也就是int3中斷),以達到整數(shù)倍的要求,也就是將預(yù)開辟空間的首地址后移幾個字節(jié)。


3)在數(shù)據(jù)成員完成各自對齊之后,結(jié)構(gòu)(或聯(lián)合)本身也要進行對齊,對齊將按照MIN(指定的#pragma pack()的數(shù)值,MAX(結(jié)構(gòu)(或聯(lián)合)數(shù)據(jù)成員長度))進行對齊。

這部分以這段代碼為例:
 1#include <iostream>
 2using namespace std;
 3struct A
 4
 5    char c; 
 6    int i; 
 7    short s;
 8}
;
 9int main ()
10
11    A a; 
12    a.c=1;a.i=2;a.s=3;
13    printf("sizeof(A)=%d\n",sizeof(A)); 
14    return 0;
15}
這里,我們采用系統(tǒng)默認的#pragma pack(8),則
c 的對齊模數(shù)為:MIN(sizeof(char),8)=MIN(1,8)=1
i  的對齊模數(shù)為:MIN(sizeof(int),8)=MIN(4,8)=4
s 的對齊模數(shù)為:MIN(sizeof(short),8)=MIN(2,8)=2
根據(jù)規(guī)則一:

根據(jù)規(guī)則二:
當給c開辟空間以后,為i開辟空間之前,編譯器先檢查與開辟空間的首地址,發(fā)現(xiàn)為1,不是i的對齊模數(shù)的整數(shù)倍,則向后找,一直到地址4時,以4為起始,向后開辟四個字節(jié)大小的空間,而之前的1,2,3這三處則填充 CC ,如下圖:

根據(jù)規(guī)則三:
現(xiàn)在進行結(jié)構(gòu)體對齊,整個sizeof(A)=10,而MIN(8,MAX(sizeof(c),sizeof(i),sizeof(s)))=4,則sizeof(A)=MIN(4N),并且sizeof(A)>=10,故,sizeof(A)=12.再將10,11空間給填充上CC:

要知道為什么有的是CC,有的是00啊,還有,千萬別看到sizeof(A)=12,就把12位置也給填上CC啊

本來打算寫一篇嘮叨完,但我太絮叨了,一個問題說了這么多,分開寫吧……