(1)什么是字節(jié)對(duì)齊
一個(gè)變量占用 n 個(gè)字節(jié),則該變量的起始地址必須能夠被 n 整除,即: 每個(gè)變量的起始存放地址 % n = 0,
對(duì)于結(jié)構(gòu)體,這個(gè) n 取其成員種的數(shù)據(jù)類型占空間的值最大的那個(gè)。
即:A1存儲(chǔ)地址addr1%A1對(duì)齊值=0,A2按順序后延,如果下一個(gè)地址addr2%A2!=0就補(bǔ)空,后移存儲(chǔ)地址addr3。若addr3%A2!=0,繼續(xù)后移。
同時(shí),每個(gè)內(nèi)存塊為最大的對(duì)齊值N,不滿的要補(bǔ)空。
結(jié)構(gòu)體中有結(jié)構(gòu)體,把內(nèi)中的結(jié)構(gòu)體拆開看。
(2)為什么要字節(jié)對(duì)齊
內(nèi)存空間是按照字節(jié)來劃分的,從理論上說對(duì)內(nèi)存空間的訪問可以從任何地址開始,但是在實(shí)際上不同架構(gòu)的CPU為了提高訪問內(nèi)存的速度,就規(guī)定了對(duì)于某些類型的數(shù)據(jù)只能從特定的起始位置開始訪問。這樣就決定了各種數(shù)據(jù)類型只能按照相應(yīng)的規(guī)則在內(nèi)存空間中存放,而不能一個(gè)接一個(gè)的順序排列。
舉個(gè)例子,比如有些平臺(tái)訪問內(nèi)存地址都從偶數(shù)地址開始,對(duì)于一個(gè)int型(假設(shè)32位系統(tǒng)),如果從偶數(shù)地址開始的地方存放,這樣一個(gè)讀周期就可以讀出這個(gè)int數(shù)據(jù),但是如果從奇數(shù)地址開始的地址存放,就需要兩個(gè)讀周期,并對(duì)兩次讀出的結(jié)果的高低字節(jié)進(jìn)行拼湊才能得到這個(gè)int數(shù)據(jù),這樣明顯降低了讀取的效率。
(3)如何進(jìn)行字節(jié)對(duì)齊
每個(gè)成員按其類型的對(duì)齊參數(shù)(通常是這個(gè)類型的大小)和指定對(duì)齊參數(shù)(不指定則取默認(rèn)值)中較小的一個(gè)對(duì)齊,并且結(jié)構(gòu)的長(zhǎng)度必須為所用過的所有對(duì)齊參數(shù)的整數(shù)倍,不夠就補(bǔ)空字節(jié)。
這個(gè)規(guī)則有點(diǎn)苦澀,可以把這個(gè)規(guī)則分解一下,前半句的意思先獲得對(duì)齊值后與指定對(duì)齊值進(jìn)行比較,其中對(duì)齊值獲得方式如下:
1. 數(shù)據(jù)類型的自身對(duì)齊值為:對(duì)于char型數(shù)據(jù),其自身對(duì)齊值為1,對(duì)于short型為2,對(duì)于int, long, float類型,其自身對(duì)齊值為4,對(duì)于 double 類型其自身對(duì)齊值為8,單位為字節(jié)。
2.結(jié)構(gòu)體自身對(duì)齊值:其成員中自身對(duì)齊值最大的那個(gè)值。
其中指定對(duì)齊值獲得方式如下:
#pragma pack (value)時(shí)的指定對(duì)齊值value。
未指定則取默認(rèn)值。
后半句的意思是主要是針對(duì)于結(jié)構(gòu)體的長(zhǎng)度而言,對(duì)于結(jié)構(gòu)體,它可能使用了多種數(shù)據(jù)類型,那么這句話翻譯成對(duì)齊規(guī)則: 每個(gè)成員的起始地址 % 自身對(duì)齊值 = 0,如果不等于 0 則地址后移直到符合規(guī)則,前面的補(bǔ)空達(dá)到對(duì)齊值。
換句話說,對(duì)于結(jié)構(gòu)體而言,結(jié)構(gòu)體在在內(nèi)存的存放順序用如下規(guī)則即可映射出來:
(一)單獨(dú)的每個(gè)成員的起始地址 % 每個(gè)成員的自身對(duì)齊值 = 0,如果不等于 0 就后移,前面補(bǔ)空使得每個(gè)成員內(nèi)存塊為結(jié)構(gòu)體中最大的對(duì)齊值。
(二)結(jié)構(gòu)體的長(zhǎng)度必須為結(jié)構(gòu)體的自身對(duì)齊值的整數(shù)倍,不夠就補(bǔ)空字節(jié)。
舉例:
typedef struct
{
char aa;
short ab;
char ac;
long ad;
}A;
sizeof(A) 結(jié)果為: 12 內(nèi)存位置為: $*$$ $*** $$$$ 注意:每個(gè)成員首地址必須為自身對(duì)齊值的整數(shù)倍。
typedef struct
{
long ba;
short bb;
long bc;
char bd;
short be;
}B;
sizeof(B)結(jié)果為:16 內(nèi)存位置為:$$$$ $$** $$$$ $*$$
typedef struct
{
char ca;
char cb;
short cc;
char cd;
short ce;
A cf;
char cg;
short ch;
long ci;
}C;
sizeof(C)結(jié)果為:28 內(nèi)存位置為:$$$$ $*$$ $*$$ $*** $$$$ $*$$ $$$$
歡迎光臨 (http://www.torrancerestoration.com/bbs/) | Powered by Discuz! X3.1 |