由一道題引出的C++位域問題
題目如下(來源於牛客網):
struct s
{
int x: 3;
int y: 4;
int z: 5;
double a;
}
求sizeof(s).(答案為16位元組)
題目理解
首先說明題目中定義x,y,z的語法
結構體成員x,y,z,是C++語法中int型別的位域.其宣告形式為在成員名字之後緊跟一個冒號以及一個常量表達式,該表示式用於指定成員所佔的二進位制位數.如果可能的話,在類的內部連續定義的位域壓縮在同一整數的相鄰位,從而提供儲存壓縮(C++ primer第五版P756).
關於本題
經測試(Debian Linux 3.16-amd64核心),int所佔位元組數為4,double所佔位元組數為8,s所佔的位元組數確實為16.一個int完全可以儲存x,y,z三個變數,為什麼不是4+8=12?
這就涉及到類中成員變數儲存時資料對齊的問題.64位Linux下,任何K位元組基本物件你的地址都必須是K的整數倍.且結構體的整體大小必須可被本結構內的最寬型別整除.
所以x,y,z總共佔一個int的大小(4位元組),成員a的起始地址為4,不符合第一條規定,故需要填充4個空白位元組,a的起始地址為4+4=8,所以結構體s的大小為8+8=16,符合第二條規定.
補充(此部分系轉載,原文傳送門)
1.一個位域必須儲存在同一個位元組中,不能跨兩個位元組。如一個位元組所剩空間不夠存放另一位域時,應從下一單元起存放該位域。也可以有意使某位域從下一單元開始。例如:
struct bs
{
unsigned a:4
unsigned b:5 /從下一單元開始存放/
unsigned c:4
};
2. 由於位域不允許跨兩個位元組,因此位域的長度不能大於一個位元組的長度。
3. 位域可以無位域名,這時它只用來作填充或調整位置。無名的位域是不能使用的。例如:
struct k
{
int a:1
int :2 /無位域名,該2位不能使用
int b:3
int c:2
};