内存对齐和内存补齐
1. 何為內(nèi)存對(duì)齊,內(nèi)存補(bǔ)齊
-內(nèi)存對(duì)齊: 第一個(gè)數(shù)據(jù)成員放在offset為0的地方,對(duì)齊按照對(duì)齊系數(shù)和自身所占用的字節(jié)數(shù)中,兩者比較小的那個(gè)進(jìn)行對(duì)齊。
-內(nèi)存補(bǔ)齊 在struct或者union數(shù)據(jù)成員完成各自對(duì)齊之后,struct或者union本身也要對(duì)齊,對(duì)齊按照對(duì)齊系數(shù)和struct或者union中最大數(shù)據(jù)成員長(zhǎng)度中比較小的那個(gè)進(jìn)行。先局部成員對(duì)齊,然后再全局對(duì)齊。
2.內(nèi)存對(duì)齊優(yōu)點(diǎn)
性能原因:數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對(duì)齊。內(nèi)存是一組一組讀取的(4個(gè)一組或8個(gè)一組讀取),為了訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn);而對(duì)齊的內(nèi)存訪問(wèn)僅需要一次訪問(wèn)(數(shù)據(jù)存放在同一個(gè)組只需要一次讀取,如果分散在不同的組,需要兩次讀取)。
3.例題解答
struct One{double d;char c;int i; } struct Two{char c;double d;int i; }問(wèn)在#pragma pack(4)和#pragma pack(8)的情況下,結(jié)構(gòu)體的大小分別是多少?
(1)針對(duì)#pragma pack(4)
Struct One:
內(nèi)存對(duì)齊: double 占8個(gè)字節(jié)(對(duì)齊系數(shù)是4,double占據(jù)8個(gè)字節(jié),兩者取小的,所以對(duì)齊系數(shù)是4),偏移量從0開(kāi)始,d占據(jù)8個(gè)字節(jié)。c占據(jù)1個(gè)字節(jié)(對(duì)齊系數(shù)是4,1和4兩者取最小值),c實(shí)際占據(jù)第8個(gè)字節(jié)。i占據(jù)4個(gè)字節(jié)(對(duì)齊系數(shù)就是4),下一個(gè)地址為12為4的倍數(shù),因此,i占據(jù)從12-15的字節(jié)。中間第9,10,11將被空出。
內(nèi)存補(bǔ)齊:內(nèi)存對(duì)齊系數(shù)為4,最大內(nèi)存長(zhǎng)度是8,因此下一個(gè)內(nèi)存地址位將按照4的倍數(shù)進(jìn)行補(bǔ)齊,由于下一個(gè)地址位是16,因此無(wú)需進(jìn)行補(bǔ)齊。所以在#pragma pack(4)情況下,struct One所需內(nèi)存為16字節(jié)。
Struct Two:
內(nèi)存對(duì)齊: c占用內(nèi)存1個(gè)字節(jié)(內(nèi)存系數(shù)是4,對(duì)齊方式1和4取小),占用第0號(hào)內(nèi)存。d占用內(nèi)存是8個(gè)字節(jié)(內(nèi)存系統(tǒng)是4,8和4取小的,所以內(nèi)存系數(shù)是4),d占據(jù)內(nèi)存位置為4-11,i占4個(gè)字節(jié)(內(nèi)存對(duì)齊方式按照4的倍數(shù)),占用12-15位內(nèi)存。中間的第1,2,3地址位將被空出。
內(nèi)存補(bǔ)齊:內(nèi)存對(duì)齊系數(shù)為4,最大內(nèi)存長(zhǎng)度是8,因此下一個(gè)內(nèi)存地址位將按照4的倍數(shù)進(jìn)行補(bǔ)齊,由于下一個(gè)地址位是16,因此無(wú)需進(jìn)行補(bǔ)齊。所以在#pragma pack(4)情況下,struct Two所需內(nèi)存為16字節(jié)。
(1)針對(duì)#pragma pack(8)
Struct One:
內(nèi)存對(duì)齊: double 占8個(gè)字節(jié)(對(duì)齊系數(shù)是8,double占據(jù)8個(gè)字節(jié),內(nèi)存對(duì)齊方式是8的倍數(shù)),偏移量從0開(kāi)始,d占據(jù)8個(gè)字節(jié)。c占據(jù)1個(gè)字節(jié)(對(duì)齊系數(shù)是8,1和8兩者取小的值),c實(shí)際占據(jù)第8個(gè)字節(jié)。i占據(jù)4個(gè)字節(jié)(對(duì)齊系數(shù)就是8,8和4取小的值),下一個(gè)地址為12為4的倍數(shù),因此,i占據(jù)從12-15的字節(jié)。中間第9,10,11將被空出。
內(nèi)存補(bǔ)齊:內(nèi)存對(duì)齊系數(shù)為8,最大內(nèi)存長(zhǎng)度是8,因此下一個(gè)內(nèi)存地址位將按照4的倍數(shù)進(jìn)行補(bǔ)齊,由于下一個(gè)地址位是16,因此無(wú)需進(jìn)行補(bǔ)齊。所以在#pragma pack(8)情況下,struct One所需內(nèi)存為16字節(jié)。
Struct Two:
內(nèi)存對(duì)齊: c占用內(nèi)存1個(gè)字節(jié)(內(nèi)存系數(shù)是8,對(duì)齊方式1和8取小),占用第0號(hào)內(nèi)存。d占用內(nèi)存是8個(gè)字節(jié)(內(nèi)存系統(tǒng)是8,所以內(nèi)存系數(shù)是8),d占據(jù)內(nèi)存位置為8-15,i占4個(gè)字節(jié)(內(nèi)存系數(shù)是8,所以對(duì)齊方式按照4的倍數(shù)),占用16-19位內(nèi)存。中間的第1,2,3,4,5,6,7地址位將被空出。
內(nèi)存補(bǔ)齊:內(nèi)存對(duì)齊系數(shù)為8,最大內(nèi)存長(zhǎng)度是8,因此下一個(gè)內(nèi)存地址位將按照8的倍數(shù)進(jìn)行補(bǔ)齊,由于下一個(gè)地址位是20,并非8的倍數(shù),因此需要進(jìn)行補(bǔ)齊到第23位(內(nèi)存地址位從第0號(hào)開(kāi)始)。所以在#pragma pack(8)情況下,struct Two所需內(nèi)存為24字節(jié)。
注:32位機(jī)器默認(rèn)對(duì)齊系數(shù)是4位,64位機(jī)器默認(rèn)對(duì)齊系數(shù)是8位。
Union在內(nèi)存中占用以最長(zhǎng)的一致
總結(jié)
- 上一篇: Ubuntu16.04通过GPT挂载硬盘
- 下一篇: wxParse无法解析strong标签