Struct memory layout in C

eonil picture eonil · May 1, 2010 · Viewed 105.3k times · Source

I have a C# background. I am very much a newbie to a low-level language like C.

In C#, struct's memory is laid out by the compiler by default. The compiler can re-order data fields or pad additional bits between fields implicitly. So, I had to specify some special attribute to override this behavior for exact layout.

AFAIK, C does not reorder or align memory layout of a struct by default. However, I heard there's a little exception that is very hard to find.

What is C's memory layout behavior? What should be re-ordered/aligned and not?

Answer

dan04 picture dan04 · May 1, 2010

It's implementation-specific, but in practice the rule (in the absence of #pragma pack or the like) is:

  • Struct members are stored in the order they are declared. (This is required by the C99 standard, as mentioned here earlier.)
  • If necessary, padding is added before each struct member, to ensure correct alignment.
  • Each primitive type T requires an alignment of sizeof(T) bytes.

So, given the following struct:

struct ST
{
   char ch1;
   short s;
   char ch2;
   long long ll;
   int i;
};
  • ch1 is at offset 0
  • a padding byte is inserted to align...
  • s at offset 2
  • ch2 is at offset 4, immediately after s
  • 3 padding bytes are inserted to align...
  • ll at offset 8
  • i is at offset 16, right after ll
  • 4 padding bytes are added at the end so that the overall struct is a multiple of 8 bytes. I checked this on a 64-bit system: 32-bit systems may allow structs to have 4-byte alignment.

So sizeof(ST) is 24.

It can be reduced to 16 bytes by rearranging the members to avoid padding:

struct ST
{
   long long ll; // @ 0
   int i;        // @ 8
   short s;      // @ 12
   char ch1;     // @ 14
   char ch2;     // @ 15
} ST;