I am working with structs in c on linux. I started using bit fields and the "packed" attribute and I came across a wierd behavior:
struct __attribute__((packed)) { int a:12; int b:32; int c:4; } t1; struct __attribute__((packed)) { int a:12; int b; int c:4; }t2; void main() { printf("%d\n",sizeof(t1)); //output - 6 printf("%d\n",sizeof(t2)); //output - 7 }
How come both structures - that are exactly the same - take diffrent number of bytes?
Bit Fields in C Language 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.
No, you can't. Bit field can only be used with integral type variables.
Again, storage of bit fields in memory is done with a byte-by-byte, rather than bit-by-bit, transfer.
Bit fields can be used to reduce memory consumption when a program requires a number of integer variables which always will have low values. For example, in many systems storing an integer value requires two bytes (16-bits) of memory; sometimes the values to be stored actually need only one or two bits.
Your structures are not "exactly the same". Your first one has three consecutive bit-fields, the second has one bit-field, an (non bit-field) int, and then a second bit-field.
This is significant: consecutive (non-zero width) bit-fields are merged into a single memory location, while a bit-field followed by a non-bit-field are distinct memory locations.
Your first structure has a single memory location, your second has three. You can take the address of the b
member in your second struct, not in your first. Accesses to the b
member don't race with accesses the a
or c
in your second struct, but they do in your first.
Having a non-bit-field (or a zero-length bit-field) right after a bit-field member "closes" it in a sense, what follows will be a different/independent memory location/object. The compiler cannot "pack" your b
member inside the bit-field like it does in the first struct.
struct t1 // 6 bytes { int a:12; // 0:11 int b:32; // 12:43 int c:4; // 44:47 }__attribute__((packed)); struct t1 // 7 bytes { int a:12; // 0:11 int b; // 16:47 int c:4; // 48:51 }__attribute__((packed));
The regular int b
must be aligned to a byte boundary. So there is padding before it. If you put c
right next to a
this padding will no longer be necessary. You should probably do this, as accessing non-byte-aligned integers like int b:32
is slow.
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