簡體   English   中英

如何計算包含一些未命名成員和零大小位域的位域結構的大小?

[英]How is the size of structures with bit-fields are calculated which contains some unnamed members and zero sized bit-fields?

這個結構的大小是如何計算的:

struct B {
    unsigned char c1 : 1;
    unsigned char : 2;
    unsigned char c2 : 2;
    unsigned char : 0;
    unsigned char c3 : 4;
    unsigned char c4 : 1;
};

這個0在這里代表什么?,這是否意味着它正在占用0位(即沒有內存)

有人可以向我解釋一下它的大小是如何計算的嗎?

大小為 0 的位域用於指定將任何后續位域放置在單獨的字節/單元中。 所以結構的布局可能如下所示:

| c1|       |   c2  |           |      c3       | c4|           |
-----------------------------------------------------------------
|  0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15|
-----------------------------------------------------------------

如果沒有大小為 0 的字段,它可能看起來像這樣:

| c1|       |   c2  |      c3       | c4|                       |
-----------------------------------------------------------------
|  0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15|
-----------------------------------------------------------------

但是請注意,結構中位字段的順序是實現定義的,因此它可能看起來不完全像這樣。

位域長度為0表示開始一個新的存儲單元

問題中結構的一種可能布局是:

  • 成員c1的初始存儲單元,長度為 2 的未命名成員和成員c2
  • 成員c3c4的單獨存儲單元。

這兩個存儲單元都可以小到一個字節,因為每個只包含 5 位信息,使struct B成為 2 字節 object,即: sizeof(struct B) == 2 但是其他大小也是可能的,因為存儲單元的選擇是實現定義的,並且成員之間和結構末尾的額外填充也是可能的。 任何大於2的大小都是可能的。 有爭議的是,即使在一個字節可以存儲至少 10 位的架構上,大小1也是不可能的,因為unsigned char: 0; 成員規范。

以下是 C 標准中的定義:

6.7.2.1 結構和聯合說明符

約束
[...]
4指定位域寬度的表達式應為 integer 常量表達式,其非負值不超過將指定類型的 object 的寬度,如果省略冒號和表達式。 如果值為零,則聲明不應有聲明符。

5位域的類型應為_Boolsigned intunsigned int或其他一些實現定義的類型的合格或非合格版本。 是否允許原子類型是實現定義的。

語義
[...]
9結構或聯合的成員可以具有除可變修改類型之外的任何完整 object 類型。 此外,可以聲明一個成員由指定數量的位組成(包括符號位,如果有的話)。 這樣的成員稱為位域; 它的寬度前面有一個冒號。

10位字段被解釋為具有由指定位數組成的有符號或無符號 integer 類型。 如果值 0 或 1 存儲到_Bool類型的非零寬度位域中,則位域的值應與存儲的值進行比較; _Bool位域具有_Bool的語義。

11實現可以分配任何大到足以容納位字段的可尋址存儲單元。 如果有足夠的空間剩余,緊跟在結構中另一個位域之后的位域將被打包到同一單元的相鄰位中。 如果剩余空間不足,則將不適合的位域放入下一個單元還是與相鄰單元重疊是實現定義的。 單元內位域的分配順序(高位到低位或低位到高位)是實現定義的。 可尋址存儲單元的 alignment 未指定。

12沒有聲明符但只有冒號和寬度的位域聲明表示未命名的位域。 作為一種特殊情況,寬度為0的位域結構成員表示不再將位域打包到放置前一個位域(如果有的話)的單元中。

因此,實現定義了c1c2如何放置在它們的公共存儲單元中, c3c4也是如此。 10意味着分配單元的選擇是實現定義的,因此struct B的大小也是實現定義的:它可以是248等。事實上,存儲單元不需要具有相同的size 和 padding 是允許的,因此理論上任何大於1的大小都是可能的。

缺乏更精確和可移植的位域規范會適得其反,因為這些規范將很好地適應 map 物理硬件設備。 早期 C 編譯器的實現差異以及與字節序約束相關的實際約束促使規范和實現變化的這種靈活性,特別是在有符號位字段方面,使程序員不願意使用此功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM