简体   繁体   中英

Bit-field expression in C structure

I found a code segment for a structure as below:

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

I wonder what the difference is between that and the definition as below:

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

Are there any possible reasons behind this?

Although the allocation of objects that contain bit-fields is implementation-defined, the C Standard does specify that consecutive bit-field members of a structure shall be packed into the same 'unit', if sufficient space remains in that unit.

From this Draft C11 Standard (bold emphasis mine):

6.7.2.1 Structure and union specifiers


11 An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.

Thus, in your first structure, the first three fields could be packed into one 8-bit unit but, then, the fourth must be placed in a separate, 32-bit unit (which will likely require 4-byte alignment, thus increasing the overall size of the structure to 8 bytes). What also may be significant in such a case is that padding bytes will be added to the structure, which may cause issues if your code relies on contiguous bits.

However, in the second case, all four bit-fields can be placed in a single 32-bit unit, so the structure size can be reduced to just 4 bytes.

But note that this may vary between compilers and platforms – notably, as demonstrated in the Compiler Explorer example linked in the comments , an implementation is entitled to allocate a 32-bit unit for the first three members of the first structure.

On Windows, using the clang-cl compiler in Visual Studio 2022, I get the aforementioned size difference between the structures when compiling and running the following code:

#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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM