sizeof(AA) and sizeof(BB) both come out as 16 even though they "should" be 12. I pack sequences of these structs into NSData objects (at which point they are 12 bytes) and pass them (NSPipe) to some subprocesses (NSTask) running independently. As such, sizeof(struct …) is important in the conversion of NSData to something else.
I believe that the C standard allows the compiler to add padding for performance/architecture reasons. As such, it is possible that doubles need to start at 8-byte memory addresses, and therefore would force padding between the earlier 32-bit chunks (I've only got a 32b machine, and both GCC and CLang give me 12 bytes).
Ever since the PowerPC days, it has been recommended to place larger data member before, such as:
struct AA { double val; int n; };
which might give you a tighter sizeof() result.
That said, int/short/long/long long sizes are somewhat variable across compilers and architectures, and you should use int8_t/int16_t/int32_t/int64_t, which are defined in stdint.h, and rarely missing from compilers nowadays (floats and doubles are pretty much 32b and 64b everywhere they represent IEEE 754 values, which is pretty much standard these days). BTW, those are guaranteed to be *at least* the number of bits (IIRC); technically, they could still be larger (so add some test unit/runtime check if you want to detect such situation), but I haven't encountered such a case ever since I started using them.
Finally, note that you might be interested in using unions, such as:
struct AA_or_BB { double val; union { int32_t i32; int16_t i16[2]; }; };
Or maybe not; it depends on your case. I just thought I should mention it.
Also, as Lance pointed out, there are pragmas that allow to force some alignments. |