內(nèi)存對齊

這幾天重新看了C語言的基礎(chǔ)知識,感覺內(nèi)存對齊太重要了憎亚,應(yīng)該把它記下來。個(gè)人感覺內(nèi)存對齊是為了適應(yīng)數(shù)據(jù)總線的寬度N弄慰,因?yàn)镃PU從內(nèi)存中取值如果按照N的整數(shù)倍第美,效率會更高。

基本數(shù)據(jù)對齊

32位操作系統(tǒng)
a.一個(gè) char(占用1-byte),變量以1-byte對齊陆爽。

b.一個(gè)short (占用2-byte),變量以2-byte對齊什往。

c.一個(gè)int (占用4-byte),變量以4-byte對齊。

d.一個(gè)long (占用4-byte),變量以4-byte對齊慌闭。

e.一個(gè)float (占用4-byte),變量以4-byte對齊别威。

f.一個(gè)double (占用8-byte),變量以8-byte對齊。

g.一個(gè)long - double (占用12-byte),變量以4-byte對齊驴剔。

h省古,任何pointer (占用4-byte) 變量以4-byte對齊。

64位操作系統(tǒng)

a.一個(gè)long (占用8-byte)變量以8-byte對齊丧失。

b.一個(gè)double (占用8-byte)變量以8-byte對齊

c.一個(gè)long double (占用16-byte) 變量以16-byte對齊

d豺妓、任何pointer (占用8-byte)變量以8-byte對齊。

2布讹、結(jié)構(gòu)體數(shù)據(jù)對齊
結(jié)構(gòu)體數(shù)據(jù)對齊琳拭,是指結(jié)構(gòu)體內(nèi)的各個(gè)數(shù)據(jù)對齊。在結(jié)構(gòu)體中的第一個(gè)成員的首地址等于整個(gè)結(jié)構(gòu)體的變量的首地址描验,而后的成員的地址隨著它聲明的順序和實(shí)際占用的字節(jié)數(shù)遞增白嘁。為了總的結(jié)構(gòu)體大小對齊,會在結(jié)構(gòu)體中插入一些沒有實(shí)際意思的字符來填充(padding)結(jié)構(gòu)體膘流。
在結(jié)構(gòu)體中絮缅,成員數(shù)據(jù)對齊滿足以下規(guī)則:
a鲁沥、結(jié)構(gòu)體中的第一個(gè)成員的首地址也即是結(jié)構(gòu)體變量的首地址。
b盟蚣、結(jié)構(gòu)體中的每一個(gè)成員的首地址相對于結(jié)構(gòu)體的首地址的偏移量(offset)是該成員數(shù)據(jù)類型大小的整數(shù)倍黍析。
c、結(jié)構(gòu)體的總大小是對齊模數(shù)(對齊模數(shù)等于#pragma pack(n)所指定的n與結(jié)構(gòu)體中最大數(shù)據(jù)類型的成員大小的最小值)的整數(shù)倍屎开。

7:  struct
   8:  {
   9:      char a;
  10:      int b;
  11:      short c;
  12:      char d;
  13:  }dataAlign;
  14:   
  15:  struct
  16:  {
  17:      char a;
  18:      char d;
  19:      short c;
  20:      int b;
  21:      
  22:  }dataAlign2;

仔細(xì)觀察阐枣,會發(fā)現(xiàn)雖然是一樣的數(shù)據(jù)類型的成員,只不過聲明的順序不同奄抽,結(jié)構(gòu)體占用的大小也不同蔼两,一個(gè)8-byte一個(gè)12-byte。為什么這樣逞度,下面進(jìn)行具體分析额划。
首先來看dataAlign2,第一個(gè)成員的地址等于結(jié)構(gòu)體變量的首地址档泽,第二個(gè)成員char類型俊戳,為了滿足規(guī)則b,它相對于結(jié)構(gòu)體的首地址的偏移量必須 是char=1的倍數(shù)馆匿,由于前面也是char抑胎,故不需要在第一個(gè)和第一個(gè)成員之間填充,直接滿足條件渐北。第三個(gè)成員short=2如果要滿足規(guī)則b阿逃,也不需 要填充,因?yàn)樗钠屏恳呀?jīng)是2赃蛛。同樣第四個(gè)也因?yàn)槠屏縤nt=4恃锉,不需要填充,這樣結(jié)構(gòu)體總共大小為8-byte呕臂。最后來驗(yàn)證規(guī)則c破托,在VC中默認(rèn) 的#pragma pack(n)中的n=8,而結(jié)構(gòu)體中數(shù)據(jù)類型大小最大的為第四個(gè)成員int=4歧蒋,故對齊模數(shù)為4,并且8 mode 4 = 0土砂,所以滿足規(guī)則c。這樣整個(gè)結(jié)構(gòu)體的總大小為8疏尿。

對齊模式n = min(max(struct_member_list),#pragma pack(n))
//當(dāng)#pragma pack(n)中的n大于結(jié)構(gòu)體中最大的成員變量所占內(nèi)存的字節(jié)數(shù)m,即n>m是瘟芝,設(shè)置將毫無意義易桃。

對于dataAlign褥琐,第一個(gè)成員等于結(jié)構(gòu)體變量首地址,偏移量為0晤郑,第二個(gè)成員為int=4敌呈,為了滿足規(guī)則b贸宏,需要在第一個(gè)成員之后填充3-byte,讓它相對于結(jié)構(gòu)體首地址偏移量為4磕洪,結(jié)合運(yùn)行結(jié)果吭练,可知&dataAlign.a = 0x01109140,而&dataAlign.b = 0x01109144析显,它們之間相隔4-byte鲫咽,0x01109141~0x01109143三個(gè)字節(jié)被0填 充。第三個(gè)成員short=2谷异,無需填充滿足規(guī)則b分尸。第四個(gè)成員char=1,也不需要填充歹嘹。結(jié)構(gòu)體總大小相加4 + 4 + 2 + 1 = 11箩绍。同樣最后需要驗(yàn)證規(guī)則c,結(jié)構(gòu)體中數(shù)據(jù)類型大小最大為第二個(gè)成員int=4尺上,比VC默認(rèn)對齊模數(shù)8小材蛛,故這個(gè)結(jié)構(gòu)體的對齊模數(shù)仍然為4,顯然11 mode 4 != 0怎抛,故為了滿足規(guī)則c卑吭,需要在char后面填充一個(gè)字節(jié),這樣結(jié)構(gòu)體變量dataAlign的總大小為4 + 4 + 2 + 2 = 12抽诉。

另外兩道練習(xí)題

typedef struct bb
{
 long age;             //[0]....[3]
 double weight;      //[8].....[15]      原則1
 float height;      //[16]..[19],總長要為8的整數(shù)倍,補(bǔ)齊[20]...[23]     原則3
}BB;

typedef struct aa
{
 char name[2];     //[0],[1]
 long  age;         //[4]...[7]          

 double score;     //[8]....[15]    
 short grade;    //[16],[17]        
 BB b;             //[24]......[47]          
}AA;

32位系統(tǒng)下面 sizeof(BB) = 24; sizeof(AA) = 48

typedef struct bb
{
 long age;             //[0]....[7]
 double weight;      //[8].....[15]      
 float height;      //[16]..[19],總長要為8的整數(shù)倍,補(bǔ)齊[20]...[23]     
}BB;

typedef struct aa
{
 char name[2];     //[0],[1]
 long  id;         //[8]...[15]         

 double score;     //[16]....[23]    
 short grade;    //[24],[25]        
 BB b;             //[32]......[55] BB結(jié)構(gòu)體的對齊模數(shù)是8陨簇,所以要以32最為開頭         
}AA;

64位系統(tǒng)下面 sizeof(BB) = 24; sizeof(AA) = 56
看到這里,以后結(jié)構(gòu)體內(nèi)定義成員變量的順序都要注意了迹淌。

留一個(gè)練習(xí)題:

typedef struct cc
{
 long double number1;    
BB  b; 
AA  Array[2];          
BB * prev; 
BB * next; 

       
}CC;

求sizeof(CC) = ??
歡迎提問河绽,不斷更新。??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末唉窃,一起剝皮案震驚了整個(gè)濱河市耙饰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纹份,老刑警劉巖苟跪,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蔓涧,居然都是意外死亡件已,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門元暴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來篷扩,“玉大人,你說我怎么就攤上這事茉盏〖矗” “怎么了枢冤?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铜秆。 經(jīng)常有香客問我淹真,道長,這世上最難降的妖魔是什么连茧? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任核蘸,我火速辦了婚禮,結(jié)果婚禮上啸驯,老公的妹妹穿的比我還像新娘值纱。我一直安慰自己,他們只是感情好坯汤,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布虐唠。 她就那樣靜靜地躺著,像睡著了一般惰聂。 火紅的嫁衣襯著肌膚如雪疆偿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天搓幌,我揣著相機(jī)與錄音杆故,去河邊找鬼。 笑死溉愁,一個(gè)胖子當(dāng)著我的面吹牛处铛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拐揭,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼撤蟆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了堂污?” 一聲冷哼從身側(cè)響起家肯,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盟猖,沒想到半個(gè)月后讨衣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡式镐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年反镇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娘汞。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歹茶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辆亏,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布鳖目,位于F島的核電站扮叨,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏领迈。R本人自食惡果不足惜彻磁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望狸捅。 院中可真熱鬧衷蜓,春花似錦、人聲如沸尘喝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朽褪。三九已至置吓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缔赠,已是汗流浹背衍锚。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嗤堰,地道東北人戴质。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像踢匣,于是被迫代替她去往敵國和親告匠。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容