The C++17 standard uses the term "allocation unit" several times in section 12.2.4 when discussing bit-fields but doesn't seem to define what the term means. The standard also states, "As a special case, an unnamed bit-field with a width of zero specifies alignment of the next bit-field at an allocation unit boundary."
So I have two questions regarding these concepts, using the code below as an example:
What does the standard mean by the term "allocation unit"?
What is the significance of the data type specified for unnamed bit-fields?
In the second question my assumption is that the data type means that the bit-field that follows should be aligned on the next boundary for that data type.
struct tag
{
char X:3;
unsigned int :0; // start next bit-field on next unsigned int boundary?
char Y:4;
unsigned char :0; // start next bit-field on next unsigned char boundary?
long Z:32;
};
Almost all of the behavior of bitfields is implementation defined, so you can't look to the standard for details of how they work.
The term "allocation unit" is deliberately vague. It's definition is really by implication:
Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit. [emphasis added] [class.bit]/1
It's up to the implementation to tell you what "allocation unit" means. The only other requirement is that an allocation unit has to be "addressable". This is the only place where the word "addressable" is used, so you're still on your own.
I believe the term "allocation unit" is referring to what the size of bit-field's type is.
CPP reference on bit-fields states:
The special unnamed bit field of size zero can be forced to break up padding. It specifies that the next bit field begins at the beginning of its allocation unit:
I have modified the example from CPP reference on bit-fields to illustrate this.
#include <iostream>
struct S1 {
unsigned char b1 : 1;
//unsigned char :0; // #1. start a new byte
unsigned char b2 : 1;
};
struct S2 {
unsigned int b1 : 10;
//unsigned int :0; // #2. start a new int
unsigned int b2 : 10;
};
int main()
{
std::cout << sizeof(char) << '\n';
std::cout << sizeof(int) << '\n';
std::cout << sizeof(S1) << '\n'; // usually prints 1
std::cout << sizeof(S2) << '\n'; // usually prints 4
}
The sizes of S1
and S2
will be 1 and 4 respectively which are also the sizes of char
and int
. This is what we would normally expect.
But if I uncomment lines #1
and #2
in the structure declarations above, the sizes of S1
and S2
will be 2
and 8
respectively. This is the consequence of the statement you have cited in the question:
As a special case, an unnamed bit-field with a width of zero specifies alignment of the next bit-field at an allocation unit boundary."
Live Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With