By Eonil


2010-05-01 05:18:19 8 Comments

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?

3 comments

@jschmier 2010-05-01 05:26:01

You can start by reading the data structure alignment wikipedia article to get a better understanding of data alignment.

From the wikipedia article:

Data alignment means putting the data at a memory offset equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.

From 6.54.8 Structure-Packing Pragmas of the GCC documentation:

For compatibility with Microsoft Windows compilers, GCC supports a set of #pragma directives which change the maximum alignment of members of structures (other than zero-width bitfields), unions, and classes subsequently defined. The n value below always is required to be a small power of two and specifies the new alignment in bytes.

  1. #pragma pack(n) simply sets the new alignment.
  2. #pragma pack() sets the alignment to the one that was in effect when compilation started (see also command line option -fpack-struct[=] see Code Gen Options).
  3. #pragma pack(push[,n]) pushes the current alignment setting on an internal stack and then optionally sets the new alignment.
  4. #pragma pack(pop) restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note that #pragma pack([n]) does not influence this internal stack; thus it is possible to have #pragma pack(push) followed by multiple #pragma pack(n) instances and finalized by a single #pragma pack(pop).

Some targets, e.g. i386 and powerpc, support the ms_struct #pragma which lays out a structure as the documented __attribute__ ((ms_struct)).

  1. #pragma ms_struct on turns on the layout for structures declared.
  2. #pragma ms_struct off turns off the layout for structures declared.
  3. #pragma ms_struct reset goes back to the default layout.

@Eonil 2010-05-01 06:07:52

Thanks for care. I modified question as you guided.

@dan04 2010-05-01 06:20:49

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;

@Deduplicator 2014-07-19 21:14:10

If neccessary, padding is added before ... More like after. Best add a final char member to your example.

@Matt 2016-01-21 10:34:05

A primitive type does not necessarily require an alignment of sizeof(T) bytes. For example, a double on common 32-bit architectures is 8 bytes but often only requires 4-byte alignment. Furthermore, the padding at the end of the struct only pads to the alignment of the widest struct member. For example, a struct of 3 char variables could have no padding.

@Potatoswatter 2010-05-01 05:26:25

In C, the compiler is allowed to dictate some alignment for every primitive type. Typically the alignment is the size of the type. But it's entirely implementation-specific.

Padding bytes are introduced so every object is properly aligned. Reordering is not allowed.

Possibly every remotely modern compiler implements #pragma pack which allows control over padding and leaves it to the programmer to comply with the ABI. (It is strictly nonstandard, though.)

From C99 ยง6.7.2.1:

12 Each non-bit-field member of a structure or union object is aligned in an implementation- defined manner appropriate to its type.

13 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

@Chris Lutz 2010-05-01 05:32:42

Some compilers (i.e. GCC) implement the same effect as #pragma pack but with more fine-grained control over the semantics.

@Potatoswatter 2010-05-01 05:37:15

I'm surprised to see a downvote. Can anyone point out the error?

@Eonil 2010-05-01 06:18:35

Thanks for care. I updated question as you guided.

@idmean 2017-01-03 12:34:47

C11 also has _Alignas.

Related Questions

Sponsored Content

28 Answered Questions

[SOLVED] When to use struct?

  • 2009-02-06 17:37:55
  • Alex Baranosky
  • 252440 View
  • 1322 Score
  • 28 Answer
  • Tags:   c# struct

24 Answered Questions

[SOLVED] When should you use a class vs a struct in C++?

  • 2008-09-10 16:29:54
  • Alan Hinchcliffe
  • 369625 View
  • 865 Score
  • 24 Answer
  • Tags:   c++ oop class struct ooad

12 Answered Questions

[SOLVED] typedef struct vs struct definitions

  • 2009-11-04 17:21:57
  • user69514
  • 627898 View
  • 742 Score
  • 12 Answer
  • Tags:   c struct typedef

11 Answered Questions

[SOLVED] Why isn't sizeof for a struct equal to the sum of sizeof of each member?

8 Answered Questions

[SOLVED] Difference between 'struct' and 'typedef struct' in C++?

  • 2009-03-04 20:41:12
  • criddell
  • 478813 View
  • 781 Score
  • 8 Answer
  • Tags:   c++ struct typedef

2 Answered Questions

[SOLVED] Precise memory layout control in Rust?

3 Answered Questions

[SOLVED] How can one not make assumptions about C++ struct layouts?

2 Answered Questions

11 Answered Questions

Sponsored Content