Are these structures padded or packed?
They're padded.
The only possibility that initially springs to mind, where they could be packed, is if char
and int
were the same size, so that the minimum size of the char/int/char
structure would allow for no padding, ditto for the int/char
structure.
However, that would require both sizeof(int)
and sizeof(char)
to be four (to get the twelve and eight sizes). The whole theory falls apart since it's guaranteed by the standard that sizeof(char)
is always one.
Were char
and int
the same width, the sizes would be one and one, not four and four. So, in order to then get a size of twelve, there would have to be padding after the final field.
When does padding or packing take place?
Whenever the compiler implementation wants it to. Compilers are free to insert padding between fields, and following the final field (but not before the first field).
This is usually done for performance as some types perform better when they're aligned on specific boundaries. There are even some architectures that will refuse to function (i.e, crash) is you try to access unaligned data (yes, I'm looking at you, ARM).
You can generally control packing/padding (which is really opposite ends of the same spectrum) with implementation-specific features such as #pragma pack
. Even if you cannot do that in your specific implementation, you can check your code at compile time to ensure it meets your requirement (using standard C features, not implementation-specific stuff).
For example:
// C11 or better ...
#include <assert.h>
struct strA { char a; int b; char c; } x;
struct strB { int b; char a; } y;
static_assert(sizeof(struct strA) == sizeof(char)*2 + sizeof(int), "No padding allowed");
static_assert(sizeof(struct strB) == sizeof(char) + sizeof(int), "No padding allowed");
Something like this will refuse to compile if there is any padding in those structures.