8

just out of curiosity, if I have a struct with bit fields

struct Foo
{
    char a : 1;
    char b : 1;
    char c : 1;
}

and another struct with bitfields and struct Foo

struct Bar
{
    Foo foo;

    char a : 1;
    char b : 1;
    char c : 1;
}

will all of these bits get packed into a single integer?

How about this case, will these fields get re-ordered to make a single bit field?

struct Baz
{
    char a : 1;

    int NotBitfield;

    char b : 1;
    char c : 1;
}
M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
  • 5
    Do you expect an answer in standard or just for specific compilers? I presume they'd be different since [multiple properties of bitfields](https://en.cppreference.com/w/cpp/language/bit_field#Notes) are implementation defined. – Louis Go May 31 '22 at 06:45
  • 1
    I think it's implemention-defined. – Yves May 31 '22 at 06:47
  • I'm working on a project in unreal engine, I searched and it says unreal engine is compiled with Visual C++ compiler-cl – M.kazem Akhgary May 31 '22 at 06:48
  • @M.kazemAkhgary You can create a function(you may want to google: convert struct to bitset), which can print a struct as a bitset. Then you can see its layout... Maybe try this one: https://stackoverflow.com/questions/36794736/casting-struct-to-int-in-c – Yves May 31 '22 at 06:50
  • @Yves thanks , I will give it a try – M.kazem Akhgary May 31 '22 at 06:56
  • bitfields are implementation-defined at best, so almost no one uses it in real code. Even [no_unique_address](https://en.cppreference.com/w/cpp/language/attributes/no_unique_address) which can help [shrink the struct size in many cases](https://stackoverflow.com/q/62784750/995714) doesn't work for bitfields in current compilers https://godbolt.org/z/WP7arPxKh – phuclv May 31 '22 at 07:06
  • regarding your last `struct Bar`, the answer is never. The standard doesn't allow that: [Can a C++ compiler re-order elements in a struct](https://stackoverflow.com/q/916600/995714), [Is there a GCC keyword to allow structure-reordering?](https://stackoverflow.com/q/14671253/995714) – phuclv May 31 '22 at 07:08
  • @phuclv: The first link tells us that members have increasing addresses. But bitfields are exempt from that rule since they don't have addresses. – MSalters May 31 '22 at 07:26
  • @phuclv I think it's still useful when it comes to serial communication with readability and ease of maintenance. However I thought it's not a portable standard. – Louis Go May 31 '22 at 07:44
  • 1
    It is also important to note that bitfields use the storage type given by the user and that is their minimum size. So `Foo` is one char and `Bar` is 2 chars. Also no member of a bitfield can cross the boundaries of the given type. `struct { char x:5; char y:5; char z:5; }` will be 3 chars (assuming 8 bit), `struct { short x:5; short y:5; short z:5; }` will be 1 short. – Goswin von Brederlow May 31 '22 at 14:18

1 Answers1

2

I'm not sure about the standard, but as this isn't a language-lawyer question, in gcc and clang sizeof(Bar) gave me two bytes - if they were packed together it'd be only one.

demo

It's possible that somewhere in the standard implies Bar must be at least two bytes; but from the above example we can certainly say that Bar is not guaranteed to be tightly packed (one byte) - at least in practice.


phuclv answered your second question in the comments by providing a link:

Section 9.2.12:

"Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1)"

So the compiler can't rearrange the data in Baz.

jaif's answer uses a nice example to illustrate the meaning of the standard here.

Elliott
  • 2,603
  • 2
  • 18
  • 35