3
votes

I have the following structures:

struct bf_struct1
{
    uint64_t bf1 : 1;
    uint64_t bf2 : 6;
    uint64_t bf3 : 2;
    uint64_t bf4 : 55;
}

struct bf_struct2
{
    uint8_t bf1 : 1;
    uint8_t bf2 : 6;
    uint8_t bf3 : 2;
    uint64_t bf4 : 55;
}

Does the structure member alignment depend on type of a bitfield members?

5
What did sizeof() tell you for the two structs? If they are both 8, I would answer "no".Charlie Burns

5 Answers

1
votes

From the horse's mouth:

6.7.2.1 Structure and union specifiers
...
5 A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type. It is implementation-defined whether atomic types are permitted.
...
11 An implementation may allocate any addressable storage unit large enough to hold a bitfield. 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.

Short answer: it can, depending on the implementation.

2
votes
#include <stdio.h>

#define uint64_t unsigned long long
#define uint8_t unsigned char

struct bf_struct1
{
    uint64_t bf1 : 1;
    uint64_t bf2 : 6;
    uint64_t bf3 : 2;
    uint64_t bf4 : 55;
};

struct bf_struct2
{
    uint8_t bf1 : 1;
    uint8_t bf2 : 6;
    uint8_t bf3 : 2;
    uint64_t bf4 : 55;
};
int main(){
    printf("%lu ", sizeof(struct bf_struct1));
    printf("%lu ", sizeof(struct bf_struct2));
    return 0;
}

Results in 8 16. So I would say the answer is yes. Compiler dependent even though gcc and clang agree on my machine. You could make some unions and figure out exactly what the alignment is.

2
votes
  • The alignment of the bit field as whole is unspecified behavior and whether a bit field is allowed to allocate unaligned is implementation-defined behavior.
  • The the bit order of a bit field is implementation-defined.
  • Because of the two remarks above, the compiler is free to add padding bits and padding bytes anywhere inside a bit field, as it pleases, in an implementation-defined manner.
  • Whether uint64_t is actually allowed inside a bit field is implementation-defined. So the code might not even work.

There is really no way to tell what this code will even do, let alone how it will be affected by alignment, without reading up on the documentation for a specific compiler.

2
votes
Does the structure member alignment depend on type of a bitfield members?  

Yes.

Check for byte offset and bit offset.

However, alignment rules for aggregates containing bit fields are different depending on the alignment mode in effect.
enter image description here

These rules are described Here.

1
votes

Yes, it can affect it. In the first given example, all of the fields can fit into a single 64-bit uint64-t, so the structure likely takes 8 bytes total. With the second, though, it would likely be 16 bytes total. The first three fields would require at least two bytes (two uint8_t). Then the last bit field of 55 bits would take a single uint64_t which would likely be aligned on an 8 byte boundary. So while the actual layout is compiler-dependent, the position of the bits would be different in both examples (because of the assumed padding prior to the uint64_t in the second example.

The layout would likely be something like the following (not exactly to scale):

bf_struct1

+---------------+---------+---------+-----------------------------------+
|    uint8_t    | uint8_t | Padding | uint64_t                          |
+---------------+---------+---------+-----------------------------------+
| bf1, bf2, bf3           | 48-bits | bf4                               |
+---------------+---------+---------+-----------------------------------+

bf_struct2

+-----------------------------------+
|      uint64_t                     |
+-----------------------------------+
| bf1, bf2, bf3, bf4                |
+-----------------------------------+