views:

577

answers:

3

Hi All,

Can a C++ compiler (specifically g++) re-order the internal elements of a struct?

I'm seeing some strange behaviour where I have a structure that contains something like the following:

Struct SomeStruct{
   ...
   ...
   long someLong;
   long someLongArray[25];
   unsigned long someUnsignedLong;
   unsigned long someUnsignedLongArray[8];
   unsigned long int someUnsignedLongInt;
   ...
   ...
};

When I write output this to file, the order of someUnsignedLongArray and someLongArray seem to be reversed (i.e. the elements in someLongArray[] appear after someUnsignedLong and the elements of someUnsignedLongArray[] appear after someLong). Is this possible??

Thanks


Update: As requested, I am writing out the structure using the following:

int fd = open(fspec,O_RDWR|O_CREAT|O_TRUNC,0666);
int writeRes =  write(fd,(char *)&someStruct,sizeof(SomeStruct));

For completeness, here is the full struct:

struct SomeStruct{
byte someByte;
byte someByteArray[6];
char someChar;
char someCharArray[5];
char someCharArrayArray[3][5];
short someShort;
signed short someShortArray[2];
unsigned short someUnsignedShort;
unsigned short someUnsignedShortArray[8];
int someInt;
int someIntArray[3];
int someIntArrayArrayArrayArray[4][3][2][6];
int *pSomeInt;
unsigned int someUnsignedInt;
unsigned int someUnsignedIntArray[9];
long someLong;
long someLongArray[25];
unsigned long someUnsignedLong;
unsigned long someUnsignedLongArray[8];
unsigned long int someUnsignedLongInt;
long long someLongLong;
long long someLongLongArray[5];
bool someBool;
bool someBoolArray[3];
unsigned long long someUnsignedLongLong;
unsigned long long someUnsignedLongLongArray[5];
unsigned long long someUnsignedLongLongArrayArray[5][2];
unsigned long long int *pSomeUnsignedLongLongInt;
};
+7  A: 

It can't, see http://stackoverflow.com/questions/867471/automated-field-re-ordering-in-c-structs-to-avoid-padding and http://stackoverflow.com/questions/118068/why-doesnt-gcc-optimize-structs for further information.

I don't know what you mean with "reversed", perhaps you should add some code and the output.

tstenner
When I say reversed, I mean that the elements in someUnsignedLongArray[] appear directly after someLong. I'll clarify the question.
Lehane
+10  A: 

It normally can't reorder elements, no.

An exception is if there's an access specifier separating them:

struct Foo {    
  A a;
  B b;
  C c;
private:
  D d;
  E e;
  F f;
};

a, b and c are guaranteed to be stored in this order, and d, e and f are guaranteed to be stored in order. But there is no guarantees about where a, b and c are stored relative to d, e and f.

Another thing to keep in mind is that the compiler can insert as much padding as it likes, even if it doesn't reorder anything.

Here's the relevant part of the standard:

Section 9.2.12:

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)"

jalf
just curious if you have a citation for this? I'm not saying you're wrong, but it would be useful to have a citation.
Doug T.
I think it's only PODs which can't be reordered within access-specifier blocks. Non-PODs have no order requirements at all. But since you're looking it up anyway for Doug T, and my copy is all the way upstairs, I'll let you check ;-)
Steve Jessop
oof, guess I'd better look it up then... ;)9.2.12 says "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)."@onebyone: Interestingly, it doesn't seem to say anything about POD vs non-POD. If you're sure about it, I'll let you look that one up. ;)
jalf
+1 a great find from the std and very educational
Doug T.
I'm not sure - for some reason I thought the stuff about order was in the POD section, but evidently not.
Steve Jessop
A: 

I don't know... but try to write the struct "element to element" to the file. I think it's safer.

Salu2.

Miguel Angel
It's highly probable that Lehane is writing the struct byte-by-byte, instead of element-by-element.
Eduardo León