4

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 struct to a file and reading it back doesn't restore all the data, and sizeof(data) returns 16.
What's the problem here ?

  • 3
    Padding. There is no guarantee how the compiler will distribute those bits and/or how much padding it will insert after the structure. Compilers like to end data structures on even boundaries. What constitutes an even boundary is dictated by several factors, not the least of which is the processor architecture. – Lou May 26 '11 at 17:42

4 Answers4

8

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++

Community
  • 1
  • 1
Himadri Choudhury
  • 10,217
  • 6
  • 39
  • 47
1

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.

1

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

phoxis
  • 60,131
  • 14
  • 81
  • 117
0

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 unsigneds, 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).

Bo Persson
  • 90,663
  • 31
  • 146
  • 203