1. 程式人生 > >由一道題引出的C++位域問題

由一道題引出的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
};