See the C version of this questions here.
I have two questions concerning bit fields when there are padding bits.
Say I have a struct defined as
struct T {
unsigned int x: 1;
unsigned int y: 1;
};
Struct T only has two bits actually used.
Question 1: are these two bits always the least significant bits of the underlying unsigned int? Or it is platform dependent?
Question 2: Are those unused 30 bits always initialized to 0? What does the C++ standard say about it?
In C, we can specify size (in bits) of structure and union members. The idea is to use memory efficiently when we know that the value of a field or group of fields will never exceed a limit or is within a small range. For example, consider the following declaration of date without the use of bit fields.
Again, storage of bit fields in memory is done with a byte-by-byte, rather than bit-by-bit, transfer.
In programming terminology, a bit field is a data structure that allows the programmer to allocate memory to structures and unions in bits in order to utilize computer memory in an efficient manner. Since structures and unions are user-defined data types in C, the user has an idea of how much memory will they occupy.
No, you can't. Bit field can only be used with integral type variables.
In order to understand bit fields, we need to have a clear understanding of Structures and Unions in C. In programming terminology, a bit field is a data structure that allows the programmer to allocate memory to structures and unions in bits in order to utilize computer memory in an efficient manner.
This is achieved by padding bits between the bit-fields. The size of structure 'A' is 1 byte. In structure B, the first unnamed bit-field skips 2 bits; the zero width bit-field after c2 causes c3 to start from the char boundary (so 3 bits are skipped between c2 and c3. There are 3 padding bits after c4.
The declaration of a bit-field has the following form inside a structure − The following table describes the variable elements of a bit field − An integer type that determines how a bit-field's value is interpreted. The type may be int, signed int, or unsigned int. The name of the bit-field. The number of bits in the bit-field.
In our example, adding padding after the first byte, the char would ensure that the last part of the data would be properly aligned in memory. See the below example. ( * is padding). Now, the processor or controller will directly read the 0x00000004 in one memory cycle and no bit shifting is required. We will check this with the below example.
Question 1: are these two bits always the least significant bits of the underlying unsigned int? Or it is platform dependent?
Very platform dependent. The standard even has a note just to clarify how much:
[class.bit]
1 ...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. [ Note: Bit-fields straddle allocation units on some machines and not on others. Bit-fields are assigned right-to-left on some machines, left-to-right on others. — end note ]
You can't assume much of anything about the object layout of a bit field.
Question 2: Are those unused 30 bits always initialized to 0? What does the C++ standard say about it?
Your example has a simple aggregate, so we can enumerate the possible initializations. Specifying no initializer...
T t;
... will default initialize it, leaving the members with indeterminate value. On the other hand, if you specify empty braces...
T t{};
... the object will be aggregate initialized, and so the bit fields will be initialized with {}
themselves, and set to zero. But that applies only to the members of the aggregate, which are the bit fields. It's not specified what value, if any, the padding bits take. So we cannot assume they will be initialized to zero.
Q1: Usually from low to hi (i.e. x is 1 << 0, y is 1 << 1, etc).
Q2: The value of the unused bits is undefined. On some compilers/platforms, stack initialised variables might be set to zero first (might!!), but don't count on it!! Heap allocated variables could be anything, so it's best to assume the bits are garbage. Using a slightly non standard anonymous struct buried in a union, you could do something like this to ensure the value of the bits:
union T {
unsigned intval;
struct {
unsigned x : 1;
unsigned y : 1;
};
};
T foo;
foo.intval = 0;
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