Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Packed bit fields in c structures - GCC

Tags:

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?

like image 979
Danny Cohen Avatar asked Sep 13 '14 11:09

Danny Cohen


People also ask

What is bit fields in structures C?

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.

Can we have an array of bit fields?

No, you can't. Bit field can only be used with integral type variables.

How bit fields are stored in memory?

Again, storage of bit fields in memory is done with a byte-by-byte, rather than bit-by-bit, transfer.

What is bit field with example?

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.


2 Answers

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.

like image 157
Mat Avatar answered Sep 18 '22 01:09

Mat


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.

like image 30
John Zwinck Avatar answered Sep 19 '22 01:09

John Zwinck