C bitfields memory usage
I need to deal with some data in the following form:
typedef struct{
unsigned n1 : 12;
unsigned n2 : 12;
unsigned n3 : 12;
unsigned n4 : 1;
unsigned n5 : 35;
} data;
I made sure that in total they count up to 9 bytes.
But they don't.. Writing 9 bytes of that开发者_JAVA技巧 struct to a file and reading it back doesn't restore all the data, andsizeof(data)
returns 16.
What's the problem here ?The problem is some padding is being added by the compiler for efficiency reasons.
This behavior can be overridden.
For how to do this with gcc see forcing alignment in GCC
For how to do this with visual c++ see: forcing alignment in Visual C++
Your structure is 9 bytes long. Compiler pads it to 16 bytes to be more cache friendly. This can be turned off (I do not recommend it in general) using compiler-specific directives/keywords. See data structure alignment.
You can use the gcc specific forced alignment :
typedef struct{
unsigned n1 : 12;
unsigned n2 : 12;
unsigned n3 : 12;
unsigned n4 : 1;
unsigned n5 : 35;
} data __attribute__((__packed__));
Read: http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Type-Attributes.html
This would work extremely well on a 36-bit computer. You forgot to tell us if that is what you have got...
On a more common 32-bit machine, using a 9 byte alignment would be very difficult to implement. If you create an array of these structs, you would need different code to access the fields in an object with an address modulo 0 and one with an address modulo 9.
The 12 bits of the first three fields would have to be collected from different unsigned
s, and differently depending on the address.
The packing directives in the the other answers are unlikely to work here, unless you have hardware with bit addressing (or a 36-bit CPU).
精彩评论