C структурный порядок элементов

#c #struct

#c #структура

Вопрос:

Я беру на себя часть кода .. программирование на c в Linux. Я внес небольшое изменение в структуру

 typedef struct {
  unsigned int a1;
  ..
  ..
  ..
  float f1;
  unsigned int a2;
  unsigned int a3;

  unsigned int offending; // shifted this
} test;
 

Я переместил unsigned int, оскорбляющий перед float f1, вот так:

 typedef struct {
  unsigned int a1;
  ..
  ..
  ..
  unsigned int offending;
  float f1;
  unsigned int a2;
  unsigned int a3;


} test;
 

и происходит сбой кода… в чем может быть проблема?

Важен ли порядок элементов структуры c?

Комментарии:

1. Независимо от того, изменяет ли это расположение структуры в памяти, зависит от реализации. Если у вас есть другой фрагмент кода, который ищет, скажем, 64 бита в структуре для чего-то, теперь он получает данные, которых он не ожидает. Связано ли это с другим программным обеспечением, которое не было перекомпилировано? Или это автономно. Кроме того, в зависимости от реализации это может привести к изменению общего размера типа, если оно испортит выравнивание, которое использовал компилятор.

2. «в чем может быть проблема?» — проблема с вашим кодом или проблема, с которой вы столкнулись? На первый мы не можем ответить, поскольку не видим ничего, кроме структуры typedef . Последнее, вероятно, связано с тем, что вы изменили свой макет, не понимая, как он используется во всем вашем коде, и не смогли что-то учесть (например: двоичная структура, считанная с диска предыдущих сохраненных данных со старым макетом, сокет от клиента / сервера, скомпилированный со старой версией, не зная о новой версиии т.д.).

3. Согласен с комментариями выше. Если ваш make-файл не имеет надлежащих зависимостей, он может не выполнить перекомпиляцию файлов, зависящих от этой структуры.

4. Весь аварийный код должен быть включен в вопрос, иначе мы не знаем, что может быть причиной проблемы.

5. Важно понимать, что, хотя вы обычно не используете struct offset для доступа к элементам структуры, существует множество структур данных, которые это делают. Особенно в таких структурах, как связанные списки, которые используют типы void для общих реализаций. Там порядок элементов в структуре имеет решающее значение. Изменение порядка в этом случае легко увидеть, как это может привести к сбою.

Ответ №1:

В чем может быть проблема? Зависит от остальной части кода и от того, что еще вы сделали.

Нет, порядок элементов структуры не является внутренне важным. Это делается так, когда от этого зависит другой код.

Возможные причины (не исчерпывающие):

  • Вы не перекомпилировали все, и в этой структуре или в каком-то ее аспекте есть внешняя связь.
  • Перемещая элемент, вы изменили выравнивание других элементов и / или sizeof() структуры и не компенсировали это.
  • Где-то есть литеральная константа или макрос с размером или смещением, которые зависят от этой структуры.
  • Существует ошибочный код, который никогда раньше не давал сбоев, но теперь происходит из-за изменения расположения памяти.
  • Структура используется где-то как часть другой структуры или объединения, и проблема связана с этим.
  • Существует инициализация списка с использованием {}, которая больше не соответствует порядку элементов.

Вы действительно должны предоставить подробную информацию о том, как он выходит из строя. В противном случае это догадки. И, возможно, даже тогда.

редактировать: ht @Jens.

Комментарии:

1. Более поздний код использует struct offset для доступа к элементам структуры, которые теперь получает unsigned int offending вместо float f1 .

2. @DavidC.Rankin: Разве я не использовал для этого «литеральную константу или макрос … смещение»? Какой другой случай вы имели в виду?

3. Ну, нет (по крайней мере, я изначально не привязывался к нему). Я думал об общей реализации связанного списка, которая использует адрес структуры смещение для доступа к элементу. Это не попало в постоянный или макроязык вашего третьего пункта, поскольку я изначально его прочитал. (перечитывая его, я вижу, что литеральной константой, как вы пишете, будет указанное смещение) Извините за шум.

Ответ №2:

Наиболее вероятной причиной сбоев при изменении компоновки данных является инициализация. Если в вашем коде есть старые инициализаторы, которые используют порядок объявления, внезапно поля получат другие значения, чем раньше. Поэтому современный C, начиная с C99, назначил инициализаторы, которые позволяют избежать этой проблемы:

 test toto = { 32, ... , 42, };                    // sensible to reordering
test tata = { .a1 = 32, ... , .offending = 42, }; // still the same