16

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; }; 
6
  • How do you write the struct to a file? Commented May 27, 2009 at 16:18
  • Are you certain that you are seeing what you think you are seeing? ie have you written unique bit patterns into each element and can trace them to the file? Also what #pragma pack (if any) are you using around the struct? Commented May 27, 2009 at 16:29
  • Perhaps he's writing the bytes of the struct, instead of the elements of the struct, to the file. Commented May 27, 2009 at 16:31
  • Can you replace the "..." and write a main function that exhibits the issue? It makes a difference what else is in the struct, and how you're writing it to file. Did you cast a SomeStruct* to char* and write sizeof(SomeStruct) bytes, or something else? Commented May 27, 2009 at 16:41
  • Btw: you can check the order of the fields with offsetof, without writing anything to disk. Commented May 27, 2009 at 16:47

2 Answers 2

37

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

Sign up to request clarification or add additional context in comments.

4 Comments

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.
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 ;-)
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. ;)
I'm not sure - for some reason I thought the stuff about order was in the POD section, but evidently not.
9

It can't, see Automated field re-ordering in C structs to avoid padding and Why doesn't GCC optimize structs? for further information.

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

2 Comments

When I say reversed, I mean that the elements in someUnsignedLongArray[] appear directly after someLong. I'll clarify the question.
It's not because it's not allowed to but because it's complex and breaks many things. GCC was able to do that and research on it is still being done. See Is there a GCC keyword to allow structure-reordering?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.