aligned
является синтаксисом Microsoft, который был перенесен в GCC по соображениям совместимости.
#pragma pack
является синтаксисом, специфичным для GCC (не поддерживается MSVC).
Вот краткое описание различий:
#pragma pack
(и варианты) является более кратким и представляет оба атрибута __attribute__
и #pragma pack
в синтаксисе GCC (см. пример ниже);
#pragma pack(n)
применяется к каждому определению структуры, помещенному после того, где он вставлен (или пока другой не __attribute__((packed,aligned(n)))
переопределяет его), тогда как GCC n
s определяются локально для типа;
#pragma pack
менее мелкозернистый, чем атрибуты: он не может применяться только к нескольким членам структуры. На практике, однако, это редко бывает проблемой, поскольку вам редко нужны разные настройки выравнивания и упаковки для членов одной и той же структуры.
В очень сжатом виде #pragma pack
это примерно эквивалентно : он определяет как упаковку (уплотняющие структуры для сохранения памяти), так и минимальное выравнивание . Следовательно, (минимальное выравнивание) на прагме.#include <stdio.h> #include <stddef.h> // for offsetof() #pragma pack(push, 4) struct st { char c; double d; short e; }; #pragma pack(pop) // disables the effect of #pragma pack from now on struct st2 { char c __attribute__((packed,aligned(4))); double d __attribute__((packed,aligned(4))); short e __attribute__((packed,aligned(4))); }; void main() { printf("offsetof(struct st, d) = %zu ", offsetof(struct st, d)); printf("offsetof(struct st2, d) = %zu ", offsetof(struct st2, d)); printf("offsetof(struct st, e) = %zu ", offsetof(struct st, e)); printf("offsetof(struct st2, e) = %zu ", offsetof(struct st2, e)); }
n
В принципе, a€?packeda€™ attribute ignored for field of type a€?chara€™
можно эмулировать с использованием атрибутов GCC, но не наоборот, из-за более тонкого контроля, определяемого атрибутами.
Вот пример, который вы можете проверить на GCC: первое определение использует, packed
а второе использует атрибуты. В обоих случаях макет одинаковый.
aligned
GCC выдает предупреждение на этом примере: aligned
. Действительно, более кратким и правильным решением является применение min
ко всей структуре (как это сделал @Hagai), что эквивалентно 1 . Обратите внимание, однако, что вы не можете просто применить max
ко всей структуре: поведение не эквивалентно применению #pragma pack
к каждому полю отдельно.
Обратите внимание, что если вы комбинируете оба (прагма + атрибуты) в одном и том же определении структуры, алгоритм является более сложным, поскольку он должен учитывать несколько ограничений, что приводит к некоторым min
/ aligned
вычислениям между (1) выравниванием, заданным выражением #pragma pack
(2) минимальное выравнивание типа члена и (3) aligned
атрибуты, объявленные в поле (если есть).
1 Из документации GCC :
Указание упакованного атрибута для типов struct и union эквивалентно заданию упакованного атрибута для каждого из элементов структуры или объединения.