выравнивание членов структуры - возможно ли допустить отсутствие заполнения - PullRequest
10 голосов
/ 05 июня 2011

Представьте себе структуру, состоящую из 32-битных, 16-битных и 8-битных значений элементов.Там, где порядок значений элементов таков, что каждый элемент находится на своей естественной границе.

struct Foo
{
    uint32_t a;
    uint16_t b;
    uint8_t c;
    uint8_t d;
    uint32_t e;
};

Правила выравнивания и заполнения элементов задокументированы для Visual C ++.sizeof (Foo) в VC ++. Вышеуказанная структура предсказуемо равна "12".

Теперь я почти уверен, что правило состоит в том, что не следует делать никаких предположений относительно заполнения и выравнивания, но на практике другие компиляторы делаютдругие операционные системы дают аналогичные гарантии?

Если нет, есть ли эквивалент "#pragma pack (1)" в GCC?

Ответы [ 3 ]

7 голосов
/ 05 июня 2011

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

Е.Г.

struct __attribute__((packed)) Blah { /* ... */ };
6 голосов
/ 05 июня 2011

В системах, которые действительно предлагают эти типы, весьма вероятно, что это сработает.Например, в 36-битной системе эти типы не были бы доступны в первую очередь.

GCC предоставляет атрибут

__attribute__ ((packed))

С аналогичным эффектом.

5 голосов
/ 05 июня 2011

На практике в любой системе, где существуют типы uintXX_t, вы получите желаемое выравнивание без заполнения. Не добавляйте уродливые gcc-измы, чтобы попытаться это гарантировать.

Редактировать: Чтобы понять, почему может быть вредно использовать attribute packed или aligned, это может привести к смещению всей структуры при использовании в качестве члена большая структура или в стеке. Это определенно снизит производительность и на машинах, отличных от x86, будет генерировать гораздо больший код. Это также означает, что недопустимо принимать указатель на любой член структуры, поскольку код, который обращается к значению через указатель, не будет знать, что оно может быть выровнено и, следовательно, может привести к ошибке.

Что касается необходимости, помните, что attribute относится только к компиляторам gcc и gcc. Стандарт C не оставляет выравнивание неопределенным или неуказанным. Это определяемый реализацией , что означает, что реализация требуется для дальнейшего указания и документирования , как она ведет себя. Поведение gcc заключается в том, чтобы всегда выравнивать каждый член структуры по следующей границе его естественного выравнивания (то же самое выравнивание, которое было бы при использовании вне структуры, которое обязательно является числом, которое равномерно делит размер типа) , Поскольку attribute является функцией gcc, если вы используете ее, вы уже используете компилятор, подобный gcc, но тогда, по предположению, у вас уже есть желаемое выравнивание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...