1

Consider the following program

#include <cstdio>
#include <stdint.h>

struct Foo
    {
    int32_t a;
    int32_t b;
    int32_t c;
    };

struct Bar
    {
    int32_t a;
    int32_t b;
    int16_t c;
    };

int main()
    {
    printf("sizeof(Foo)=%u\nsizeof(Bar)=%u",sizeof(Foo),sizeof(Bar));
    return 0;
    }

When compiling using MinGW I get sizeof(Foo)=12 and sizeof(Bar)=12 on both 32-bit and 64-bit systems (I guess that in a 16-bit environment, sizeof(Bar)=10). Is it likely that in the future, the size of these structures will be 16 to make the fit better in the 64-bit environment?

I'm storing structs in files, and do not want to add work-arounds in the future. The Doom thing structure layout was probably a good choice 1993 but not today.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
user877329
  • 6,717
  • 8
  • 46
  • 88
  • 2
    `` is a C++ header; do you mean ``? The correct format for a `size_t` argument is `%zu`, not `%u`; if your implementation doesn't support it, you can cast to `unsigned long` and use `%lu`. – Keith Thompson Aug 28 '12 at 08:45
  • @KeithThompson Good to know. But the listed sizes are correct anyway probably due to endianness of the x86-64 architecture (size_t is ll or I64 or what you call it) – user877329 Aug 28 '12 at 08:59

2 Answers2

6

The size of the Bar structure has little to do with whether you're on a 16-bit environment, it has solely to do with the alignment requirements of the fields within your structure.

The alignment of the structure is generally identical to the most restrictive alignment of all of the fields within it. In this case, it's the 32-bit alignment requirement of an int32_t type that's affecting it.

Now you may think that shouldn't be the case since the final field is a 16-bit value and there's nothing after it requiring further alignment, but you'd be wrong. Think of what happens with an array of those things:

0000  index 0  a      32 bits
0004           b      32 bits
0008           c      16 bits
000a           filler 16 bits
000c  index 1  a      32 bits
0010           b      32 bits
0014           c      16 bits
0018           filler 16 bits

You can see that filler is required after c due to the requirement for the following a to be correctly aligned.

In terms of the future, it would be unlikely that any of the alignments of those fields would change, simply because they are exact bit-width types. They will always be 32-bit values and probably always require a 32-bit alignment.

Having said that, there's no guarantee that you won't find an implementation that requires 32 bit values to be aligned on 128-bit boundaries at some point in the future. Section 6.2.8 Alignment of objects is the controlling section in C11, and it doesn't seem to discount this possibility since it doesn't state the the alignment is related to the object size:

An object type imposes an alignment requirement on every object of that type: stricter alignment can be requested using the _Align keyword.

If you want to catch the possibility that the structure size and/or alignment changes, you can use sizeof and alignof in your main function to output a message and exit if they're not correct. This won't affect code in the field but will help enormously if you move to a compiler with stricter alignments.

And that's the point where you change it (see YAGNI). The problem with planning for all possible futures is that you have no idea what will happen :-)

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I tried the DoomThing and RGB and yes, they are 10 and 3 bytes respectivly. – user877329 Aug 28 '12 at 08:20
  • 1
    Excellent answer. I'd also add that writing the contents of a struct directly to file is a bad idea. In addition to the alignment and padding issues mentioned here there's also the issue with endianness. To be future proof define a file format and make sure each value is written as the format requires regardless of the platform or compiler implementation. – harald Aug 28 '12 at 08:35
0

Future... For now you can use #pragma pack(1)

Slava Zhuyko
  • 691
  • 4
  • 12