2016-09-05 2 views
0

Пожалуйста, обратите внимание на следующие типы:Выравнивание объектов составного типа в C90 и C99

typedef struct { char myArray[300]; } MyStruct; 
typedef union { char myArray[300]; } MyUnion; 

typedef struct { uint64_t x; } MyStruct2; 
typedef union { uint64_t x; } MyUnion2; 

typedef struct { uint64_t x; char myArray[300]; } MyStruct3; 
typedef union { uint64_t x; char myArray[300]; } MyUnion3; 

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

Какие правила выравнивания применяются к объектам этих типов в ОЗУ с использованием C90 и C99 на платформе X86? Может быть изменено выравнивание, например. потому что оптимизатор удаляет неиспользуемые элементы (особенно в союзах)?

+5

Выравнивание объектов определяется реализацией. Вы должны использовать специальные атрибуты компилятора или _Alignas, если вы хотите установить определенное значение. – 2501

+0

Таким образом, нет абсолютно никакого переносного способа гарантировать соответствие объекта (например, с использованием членов определенного размера и т. Д.)? – Silicomancer

+1

_Alignas портативный, но это не C99. – 2501

ответ

1

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

Компилятор не может разумно убедиться в том, что член не используется, поэтому не будет удалять «неиспользуемых» членов из союзов или структур (на самом деле, союзы - это другое дело, потому что означает «неиспользованный»?).

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

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

Для объединения компилятор никогда не может быть уверен, поскольку память членов разделяется.