簡體   English   中英

C結構中的位域表達式

[英]Bit-field expression in C structure

我找到了一個結構的代碼段,如下所示:

    struct
    {
      __u8 saveable: 1;
      __u8 namespace: 1;
      __u8 changeable: 1;
      __u32 reserved: 29;
    };

我想知道這和下面的定義有什么區別:

    struct
    {
      __u32 saveable: 1;
      __u32 namespace: 1;
      __u32 changeable: 1;
      __u32 reserved: 29;
    };

這背后有什么可能的原因嗎?

盡管包含位域的對象的分配是實現定義的,但 C 標准確實規定了結構的連續位域成員應打包到相同的“單元”中,如果該單元中有足夠的空間。

這個 C11 標准草案(我的粗體強調):

6.7.2.1 結構和聯合說明符


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

因此,在您的第一個結構中,前三個字段可以打包到一個 8 位單元中,但是第四個字段必須放在一個單獨的 32 位單元中(這可能需要 4 字節 alignment,從而增加結構的總大小為 8 個字節)。 在這種情況下也可能很重要的是填充字節將添加到結構中,如果您的代碼依賴於連續位,這可能會導致問題。

然而,在第二種情況下,所有四個位域都可以放在一個32 位單元中,因此結構大小可以減少到只有 4 個字節。

但請注意,這可能因編譯器和平台而異——值得注意的是,如注釋中鏈接的編譯器資源管理器示例所示,實現有權為第一個結構的前三個成員分配一個 32 位單元。

在 Windows 上,使用 Visual Studio 2022 中的 clang-cl 編譯器,在編譯和運行以下代碼時,我得到了上述結構之間的大小差異:

#include <stdint.h>
#include <stdio.h>

struct {
    uint8_t saveable : 1;
    uint8_t namespace : 1;
    uint8_t changeable : 1;
    uint32_t reserved : 29;
} s1;

struct {
    uint32_t saveable : 1;
    uint32_t namespace : 1;
    uint32_t changeable : 1;
    uint32_t reserved : 29;
} s2;

int main()
{
    printf("Size of s1 = %zu\n", sizeof(s1));
    printf("Size of s2 = %zu\n", sizeof(s2));
    return 0;
}

Output:

Size of s1 = 8
Size of s2 = 4

暫無
暫無

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

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