C++ 位元組對齊分析,struct成員指定位大小
閱讀C++ Concurrency In Action 第5章遇到這個問題,記錄下來,方便以後回頭看
主要涉及 位域和位元組對齊問題,位域一般不常見,屬於C/C++高階特性
位域指的是針對struct成員指定位大小,位域的作用主要是節省記憶體資源,使資料結構更緊湊
原書這樣描述:
無論什麼型別,物件均被儲存於一個或多個記憶體位置中,每個這樣的記憶體位置要麼是一個標量型別的物件(或子物件),比如unsigned short 或 my_class*,要麼是相鄰位域的序列。
如果使用位域,有非常重要的一點必須注意:雖然相鄰的位域是不同的物件,但他們仍然算作相同的記憶體位置。
上圖所示的結構體 struct my_data,整個struct是一個物件,它由幾個子物件組成,各子物件對應每個資料成員。
位域bf1和bf2共享一個記憶體位置,而std::string物件在內部由幾個記憶體位置組成,但是其餘的每個成員都有自己的記憶體位置。
注意零長度的位域bf3是如何將bf4分割進它自己的記憶體位置的。
開始對上述標紅的位置不是很理解,
查閱資料瞭解,位域儲存具有如下規則:
1、如果相鄰位域欄位的型別相同,且其位寬之和小於這個型別的sizeof大小,則後面的欄位將緊鄰前一個欄位儲存,知道不能容納為止。
2、如果相鄰位域欄位的型別相同,但其位寬之和大雨型別的sizeof大小,則後面的欄位將從新的儲存單元開始,其偏移量為其型別大小整數倍。
3、如果相鄰的位域欄位的型別不同,則各編譯器的具體實現有差異,VC6採取不壓縮方式,GCC和Dev-C++採取壓縮方式。
4、如果位域之間穿插著非位域型別,則不進行壓縮。
5、整個結構體的總大小為最寬基本型別成員大小的整數倍
6、取地址操作符&不能應用在位域欄位上
7、位域欄位不能是類的靜態成員
8、位域欄位在記憶體中的位置是按照從低位向高位的順序放置的
9、當要把某個成員說明成位域時,其型別只能是int,unsigned int與signed int三者之一
根據以上規則,分析該struct佔用位元組書,sizeof(struct my_data) = 48,
分解後應該如下所示:
struct my_data { int i; //對齊後佔用8位元組, 實際使用4位元組
//空行表示需要開闢新的8位元組記憶體空間
double d; //佔用8位元組
unsigned bf1:10; //對齊後佔用4位元組,實際使用10 bit
int bf2:25; //10+25 > 32,因此佔用新的4位元組,對齊後佔用4位元組,實際使用25 bit
int bf3:0; //<span style="color: rgb(0, 128, 0); line-height: 1.5; font-family: "Courier New"; white-space: pre-wrap;">空位域,自動置0</span>
int bf4:9; //25+9 > 32,因此需要佔用新的4位元組,對齊後佔用4位元組,實際佔用9bit
int i2; //佔用4位元組
char c1, c2; //對齊佔用8位元組,實際使用2位元組
std::string s; //佔用8位元組
};
其中bf1和bf2型別不同,其實是經過壓縮儲存的,即他們可以緊鄰儲存,
經過測試,將int bf2:25 改成 int bf2:22,則sizeof(struct my_data) = 40,說明bf2是可以緊鄰bf1儲存的,說明是壓縮儲存的。
參考資料
1、http://www.cnblogs.com/hedaihong/p/4348535.html
2、c++併發程式設計實戰
3、http://www.cnblogs.com/pure/archive/2013/04/22/3034818.html