49

This is a question that was sparked by Rob Walker's answer here.

Suppose I declare a class/struct like so:

struct
{ 
    char A;
    int B;
    char C;
    int D;
};

Is it safe to assume that these members will be declared in exactly that order in memory, or is this a compiler dependent thing? I'm asking because I had always assumed that the compiler can do whatever it wants with them.

This leads into my next question. If the above example causes memory alignment issues, why can the compiler not just turn that into something like this implicitly:

struct
{ 
    char A;
    char C;
    int B;
    int D;
};

(I'm primarily asking about C++, but I'd be interested to hear the C answer as well)

Related topics

Community
  • 1
  • 1
Jason Baker
  • 192,085
  • 135
  • 376
  • 510

6 Answers6

84

C99 §6.7.2.1 clause 13 states:

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.

and goes on to say a bit more about padding and addresses. The C89 equivalent section is §6.5.2.1.

C++ is a bit more complicated. In the 1998 and 2003 standards, there is §9.2 clause 12 (clause 15 in C++11):

Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

aib
  • 45,516
  • 10
  • 73
  • 79
  • This answer nails it. The only caveat is that not all compilers follow the standard. Of the compilers that that do follow the standard, don't necessarilarly follow it at all optimization levels. – Stephen Curial Sep 29 '09 at 19:22
  • /DAMN/. I didn't know about that access-specifier exception - I'm sure I don't have any code depending on it fortunately. – Simon Buchan Jul 05 '10 at 10:16
  • 3
    C++11: It is now §9.2 clause 15: The wording of the paragraph did not change. – Andreas Florath Jan 16 '13 at 06:49
  • Does the "non-bit-field members" part of the C standard mean that the compiler is allowed to reorder named bit fields? – gsgx May 28 '13 at 19:36
  • I think it means the bit fields may be reordered, but only among themselves, i.e. those sharing the same variable. – aib Oct 12 '13 at 01:18
4

The data members are arranged in the order declared. The compiler is free to intersperse padding to arrange the memory alignment it likes (and you'll find that many compilers have a boatload a alignment specification options---useful if mixing bits compiled by different programs.).

See also Why doesn't GCC optimize structs?.


It appears that this answer is somewhat obsolete for C++. You learn something everyday. Thanks aib, Nemanja.

Community
  • 1
  • 1
dmckee --- ex-moderator kitten
  • 98,632
  • 24
  • 142
  • 234
3

I cannot speak for C++, but in C the order is guaranteed to be the same order in memory as declared in the struct.

Chris Young
  • 15,627
  • 7
  • 36
  • 42
3

Basically, you can count on that only for the classes with a standard layout. Strictly speaking, standard layout is a C++0x thing, but it is really just standardizing existing practice/

Nemanja Trifunovic
  • 24,346
  • 3
  • 50
  • 88
2

Aside from padding for alignment, no structure optimization is allowed by any compiler (that I am aware of) for C or C++. I can't speak for C++ classes, as they may be another beast entirely.

Consider your program is interfacing with system/library code on Windows but you want to use GCC. You would have to verify that GCC used an identical layout-optimization algorithm so all your structures would be packed correctly before sending them to the MS-compiled code.

Jason Baker
  • 192,085
  • 135
  • 376
  • 510
HUAGHAGUAH
  • 1,063
  • 6
  • 3
  • Really? I was always told that structs and classes are exactly the same thing with the exception of structs defaulting to public access. Or is this the subject of a whole 'nother question? – Jason Baker Nov 11 '08 at 14:53
  • 1
    C++ classes are no different from C++ structs. The *only* difference is that structs use 'public' by default for members or inheritance, while classes use 'private. – jalf Nov 11 '08 at 14:54
  • @HUAGHAGUAH - I hope you don't mind, I tweaked your post a tad. I like your post and didn't want anyone to vote it down because of the part about C++ classes being another beast entirely. :-) – Jason Baker Nov 11 '08 at 14:57
0

While browsing the related topics at the right, I looked at this question. I figure this may be an interesting corner case when thinking about these issues (unless it's more common than I realize).

To paraphrase, if you have a struct in C that looks something like this:

struct foo{};

and subclass it like so in C++ (using a separate compilation unit):

extern "C" foo;
struct bar: public foo{};

Then the memory alignment won't necessarily be the same for the reasons aib mentions (even amongst compilers from the same vendor).

Community
  • 1
  • 1
Jason Baker
  • 192,085
  • 135
  • 376
  • 510