1. 對齊
需要各類型數(shù)據(jù)按照一定的規(guī)則在內(nèi)存空間上排列动分,而不是順序的排放滨溉,這就是對齊。
2. 對齊的原因
最常見的是如果不按照適合其平臺的要求對數(shù)據(jù)存放進行對齊排列维咸,會造成存取效率的低下渠啤。例如:一個int型(假設(shè)32位)如果存放在偶地址開始的地方狐肢,則需要一個讀周期即可;如果存放在奇地址開始的地方沥曹,則可能需要2個讀周期份名,并且需要對2次讀出的結(jié)果的高低字節(jié)進行拼湊之后才能得到該int數(shù)據(jù)碟联。
3. 對齊的實現(xiàn)
四個概念值:
數(shù)據(jù)類型自身的對齊值:就是數(shù)據(jù)類型的自身對齊值。
指定對齊值:#pargma pack(value) 時的指定對齊值value僵腺。
結(jié)構(gòu)體或類的自身對齊值:其成員中自身對齊值最大的那個值鲤孵。
數(shù)據(jù)成員、結(jié)構(gòu)體和類的有效對齊值:自身對齊值和指定對齊值中較小的那個值辰如。
有效對齊值N是最終決定數(shù)據(jù)存放地址方式的值普监。有效對齊值N表示“對齊在N上”,即該數(shù)據(jù)的“存放起始地址%N=0”琉兜。數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)變量都是按定義的先后順序來排放的凯正,即第一個數(shù)據(jù)變量的起始地址就是數(shù)據(jù)結(jié)構(gòu)的起始地址。結(jié)構(gòu)體的成員變量要對齊排放豌蟋,結(jié)構(gòu)體本身也要根據(jù)自身的有效對齊值圓整(就是結(jié)構(gòu)體成員變量占用總長度需要是對結(jié)構(gòu)體有效對齊值的整數(shù)倍)廊散。
例如:
struct A {
int a;
char b;
short c;
};
struct B {
char b;
int a;
short c;
};
對于char類型數(shù)據(jù)其自身對齊值為1,對于short類型為2梧疲,對于int允睹,float,double則為4往声,單位為字節(jié)擂找。
因此A,B用到的空間都應(yīng)該是7字節(jié)浩销,但是由于編譯器要對數(shù)據(jù)成員在地址空間上進行對齊贯涎,所以sizeof(struct A)=8字節(jié),sizeof(struct B)=12字節(jié)慢洋。
假設(shè)B從地址空間0x0000開始排放成員塘雳,環(huán)境默認對齊值為4.第一個成員b的自身對齊值為1,比默認或指定對齊值4小普筹,所以其有效對齊值為1败明,且其存放地址符合0x0000%1=0;第二個成員變量a太防,其自身對齊值為4=默認對齊值4妻顶,所以其有效對齊值為4,且其存放地址為0x0004到0x0007(因為0x0001%4!=0蜒车,且0x0004緊靠第一個變量)讳嘱;第三個成員變量c自身對齊值為2<默認對齊值4,所以其有效對齊值為2酿愧,且0x0008%2=0沥潭,故c存放在0x0008到0x0009這兩個字節(jié)空間中。最后再看數(shù)據(jù)結(jié)構(gòu)B的自身對齊值為其變量中最大對齊值嬉挡,所以就是4=默認對齊值4钝鸽,所以結(jié)構(gòu)體B的有效對齊值也是4.根據(jù)結(jié)構(gòu)體圓整的要求0x0000到0x0009=10字節(jié)汇恤,(10+2)%4=0,所以0x000A和0x000B也被結(jié)構(gòu)體B占用拔恰。故sizeof(struct B)=12因谎,同理可得sizeof(struct A)=8。