I have a structure specified as following
- Member 1, 16 bits
- Member 2, 32 bits
- Member 3, 32 bits
which I shall be reading from a file. I want to read straight from the file into the struct.
The problem is that the C compiler will align the variables m1, m2 and m3 to word boundaries which are at 32 bits since I am working on an ARM Cortex M3 for the following struct declaration:
typedef struct
{
uint16_t m1;
uint32_t m2;
uint32_t m3;
}something;
Reading directly from file will put wrong values in m2 and m3, and reads 2 extra bytes too.
I have hacked around and am currently using the following which works just fine:
typedef struct
{
uint16_t m1;
struct
{
uint16_t lo;
uint16_t hi;
}m2;
struct
{
uint16_t lo;
uint16_t hi;
}m3;
}something;
However, this looks like a really dirty hack. I cannot help wishing for a cleaner way to force the compiler to put halves of m2 and m3 in different words, however sub-optimal it may be.
I am using arm-none-eabi-gcc. I know about bit packing, but am unable to work around this optimisation.
Edit: Turns out I didn't know enough about bit-packing :D
What you are looking for is the
packed
attribute. This will force gcc to not do any padding around members. Taken from the GCC Online docs:packed
This attribute, attached to an enum, struct, or union type definition, specified that the minimum required memory be used to represent the type. Specifying this attribute for struct and union types is equivalent to specifying the packed attribute on each of the structure or union members. Specifying the -fshort-enums flag on the line is equivalent to specifying the packed attribute on all enum definitions.
You may only specify this attribute after a closing curly brace on an enum definition, not in a typedef declaration, unless that declaration also contains the definition of the enum.
So what you want is something like:
In addition I would recommend using a compile time assertion check to ensure that the size of the struct is really what you want it to be.