Может ли компилятор C++ переупорядочивать элементы в структуре

Может ли компилятор С++ (в частности, g++) изменить порядок внутренних элементов структуры?

Я наблюдаю какое-то странное поведение, когда у меня есть структура, содержащая что-то вроде следующего:

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

Когда я записываю вывод в файл, порядок someUnsignedLongArray и someLongArray кажется обратным (т.е. элементы в someLongArray[] появляются после < em>someUnsignedLong, а элементы someUnsignedLongArray[] появляются после someLong). Это возможно??

Спасибо


Обновление: в соответствии с просьбой я пишу структуру, используя следующее:

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

Для полноты, вот полная структура:

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;
};

person Lehane    schedule 27.05.2009    source источник
comment
Как записать структуру в файл?   -  person tstenner    schedule 27.05.2009
comment
Вы уверены, что видите то, что, как вам кажется, видите? т.е. вы записали уникальные битовые комбинации в каждый элемент и можете проследить их до файла? Также какой пакет #pragma (если есть) вы используете для структуры?   -  person Peter M    schedule 27.05.2009
comment
Возможно, он записывает в файл байты структуры вместо элементов структуры.   -  person pyon    schedule 27.05.2009
comment
Можете ли вы заменить ... и написать основную функцию, которая демонстрирует проблему? Имеет значение, что еще находится в структуре и как вы записываете это в файл. Вы преобразовали SomeStruct* в char* и написали sizeof(SomeStruct) bytes или что-то еще?   -  person Steve Jessop    schedule 27.05.2009
comment
Кстати: вы можете проверить порядок полей с помощью offsetof, ничего не записывая на диск.   -  person Steve Jessop    schedule 27.05.2009
comment
@onebyte добавил к вопросу...   -  person Lehane    schedule 27.05.2009
comment
И вы запускаете этот код на процессоре x86? Принимая во внимание порядок байтов, обычно лучше писать каждый элемент структуры за раз (используя соответствующие макросы hton()), если вы хотите, чтобы ваш код был переносимым.   -  person Andreas Magnusson    schedule 28.05.2009


Ответы (2)


Обычно он не может переупорядочивать элементы, нет.

Исключением является наличие разделяющего их спецификатора доступа:

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

a, b и c гарантированно сохраняются в этом порядке, а d, e и f гарантированно сохраняются по порядку. Но нет никаких гарантий относительно того, где a, b и c хранятся относительно d, e и f.

Еще одна вещь, о которой следует помнить, это то, что компилятор может вставлять столько отступов, сколько ему нужно, даже если он ничего не переупорядочивает.

Вот соответствующая часть стандарта:

Раздел 9.2.12:

Нестатические члены данных (не объединенного) класса, объявленного без промежуточного спецификатора доступа, выделяются таким образом, что более поздние члены имеют более высокие адреса в объекте класса. Порядок размещения нестатических элементов данных, разделенных спецификатором доступа, не указан (11.1)"

person jalf    schedule 27.05.2009
comment
просто любопытно, если у вас есть цитата для этого? Я не говорю, что вы не правы, но было бы полезно привести цитату. - person Doug T.; 27.05.2009
comment
Я думаю, что только POD нельзя переупорядочить в блоках спецификаторов доступа. У не-POD вообще нет требований к заказу. Но так как вы все равно ищете это для Дуга Ти, а моя копия находится наверху, я позволю вам проверить ;-) - person Steve Jessop; 27.05.2009
comment
уф, думаю, тогда мне лучше поискать... ;) 9.2.12 говорит, что нестатические члены данных класса (не объединенного), объявленного без промежуточного спецификатора доступа, выделяются так, чтобы более поздние члены имели более высокие адреса внутри класса объект. Порядок размещения нестатических элементов данных, разделенных спецификатором доступа, не определен (11.1). @onebyone: Интересно, что, похоже, ничего не говорится о POD и не-POD. Если вы уверены в этом, я дам вам посмотреть на это. ;) - person jalf; 27.05.2009
comment
Я не уверен - я почему-то думал, что материал о порядке есть в разделе POD, но, видимо, это не так. - person Steve Jessop; 27.05.2009

Это невозможно, см. Автоматическое изменение порядка полей в Структуры C, чтобы избежать заполнения и Почему GCC не оптимизирует структуры? для дополнительной информации.

Я не знаю, что вы имеете в виду под «обратным», возможно, вам следует добавить код и вывод.

person tstenner    schedule 27.05.2009
comment
Когда я говорю наоборот, я имею в виду, что элементы в someUnsignedLongArray[] появляются сразу после someLong. Я уточню вопрос. - person Lehane; 27.05.2009
comment
Это не потому, что это запрещено, а потому, что это сложно и ломает многие вещи. GCC удалось это сделать, и исследования в этой области все еще ведутся. См. раздел Есть ли ключевое слово GCC, разрешающее переупорядочение структуры? - person phuclv; 04.09.2019