一第练、內(nèi)存對齊的原因
大部分的參考資料都是如是說的:
平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的翔试;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常复旬。
性能原因:數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對齊垦缅。原因在于,為了訪問未對齊的內(nèi)存驹碍,處理器需要作兩次內(nèi)存訪問壁涎;而對齊的內(nèi)存訪問僅需要一次訪問。
二志秃、對齊規(guī)則
每個特定平臺上的編譯器都有自己的默認(rèn)“對齊系數(shù)”(也叫對齊模數(shù))怔球。比如32位系統(tǒng)默認(rèn)對齊系數(shù)是 4, 64位的則可以達到 8.
程序員可以通過預(yù)編譯命令
#pragma pack(n) // n=1,2,4,8,16
來改變這一系數(shù)浮还,其中的n就是指定的“對齊系數(shù)”竟坛。
另外,可以通過GCC提供的 __attribute__
擴展機制取消對齊優(yōu)化钧舌。
規(guī)則:
數(shù)據(jù)成員對齊規(guī)則:結(jié)構(gòu)(struct)或聯(lián)合(union)的數(shù)據(jù)成員担汤,第一個數(shù)據(jù)成員放在offset為0的地方,以后每個數(shù)據(jù)成員的對齊按照
#pragma pack
指定的數(shù)值和這個數(shù)據(jù)成員自身長度中洼冻,比較小的那個進行崭歧。結(jié)構(gòu)(或聯(lián)合)的整體對齊規(guī)則:在數(shù)據(jù)成員完成各自對齊之后,結(jié)構(gòu)(或聯(lián)合)本身也要進行對齊撞牢,對齊將按照
#pragma pack
指定的數(shù)值和結(jié)構(gòu)(或聯(lián)合)最大數(shù)據(jù)成員長度中率碾,比較小的那個進行叔营。
三、試驗
下面通過一例子的說明這個規(guī)則
編譯器:GCC4.6.3, (g++)
操作系統(tǒng):Ubuntu 12所宰, Windows 7
struct test {
short a;
double b;
int c;
char d;
};
在GCC中绒尊,各類型的大小如下:
sizeof(char)) = 1
sizeof(short) = 2
sizeof(int) = 4
sizeof(float) = 4
sizeof(double) = 8
sizeof(long long) = 8
注解:在32位系統(tǒng),n=4
相當(dāng)于:
#pragma pack(4)
struct test {
short a; // 按2字節(jié)對齊仔粥,存放區(qū)間:0-1
double b; // 按4字節(jié)對齊婴谱,存放區(qū)間:4-11
int c; // 按4字節(jié)對齊,存放區(qū)間:12-15
char d; // 按1字節(jié)對齊件炉,存放區(qū)間:16
};
#pragma pack()
最后整體對齊勘究,按4圓整矮湘,故:
sizeof(test) = 20
注解:在64位系統(tǒng)斟冕,默認(rèn)的對齊系數(shù)為8
struct test {
short a; // 按2字節(jié)對齊,存放區(qū)間:0-1
double b; // 按8字節(jié)對齊缅阳,存放區(qū)間:8-15
int c; // 按4字節(jié)對齊磕蛇,存放區(qū)間:16-19
char d; // 按1字節(jié)對齊,存放區(qū)間:20
};
最后整體對齊十办,按8圓整秀撇,故:
sizeof(test) = 24
注解:C++允許在結(jié)構(gòu)體中定義static變量,靜態(tài)變量分配在同一的靜態(tài)存儲區(qū)向族,不包含在結(jié)構(gòu)體大小中呵燕。
如下:
#pragma pack(4)
struct test {
short a;
double b;
int c;
char d;
static int d;
};
#pragma pack()
該結(jié)構(gòu)體的大小仍為 20.
在標(biāo)準(zhǔn)C,似乎并沒有這種用法件相。
【原文鏈接:http://mirreal.github.io/blog/2014/09/15/memory-alignment/】