Например:
#pragma pack(L1_CACHE_LINE)
struct A {
//...
};
#pragma pack()
A a;
и
struct A {
//...
};
A a __attritube__((aligned(L1_CACHE_LINE)))
Какая разница между thwm?
Спасибо заранее!
Например:
#pragma pack(L1_CACHE_LINE)
struct A {
//...
};
#pragma pack()
A a;
и
struct A {
//...
};
A a __attritube__((aligned(L1_CACHE_LINE)))
Какая разница между thwm?
Спасибо заранее!
Пакет #pragma (байт-выравнивание) влияет на каждый член структуры, заданный входным элементом выравнивания по байтам, или на их границе естественного выравнивания, в зависимости от того, что меньше.
__attribute__((aligned(byte-alignment)))
влияет на минимальное выравнивание переменной (или struct field, если указано в структуре)
Я считаю, что следующие эквиваленты
#define L1_CACHE_LINE 2
struct A
{
u_int32_t a __attribute__ ( (aligned(L1_CACHE_LINE)) );
u_int32_t b __attribute__ ( (aligned(L1_CACHE_LINE)) );
u_int16_t c __attribute__ ( (aligned(L1_CACHE_LINE)) );
u_int16_t d __attribute__ ( (aligned(L1_CACHE_LINE)) );
u_int32_t e __attribute__ ( (aligned(L1_CACHE_LINE)) );
};
#pragma pack(L1_CACHE_LINE)
struct A
{
u_int32_t a;
u_int32_t b;
u_int16_t c;
u_int16_t d;
u_int32_t e;
};
#pragma pack()
где A a __attritube__((aligned(L1_CACHE_LINE)))
обеспечит u_int32_t a
внутри struct A
, будет выровнен с 2 байтами, но не будет выравнивать другую переменную таким же образом.
Ссылка:
#pragma pack
является синтаксисом Microsoft, который был портирован в GCC по причинам совместимости.
__attribute__((aligned))
- это специфический для GCC синтаксис (не поддерживается MSVC).
Вот краткое описание различий:
#pragma pack
(и варианты) является более кратким и представляет оба атрибуты packed
и aligned
в синтаксисе GCC (см. пример ниже);#pragma pack
применяется к каждому определению структуры, помещенному после того, где он вставлен (или пока другой #pragma pack
не переопределяет его), тогда как GCC __attribute__
локально определены для типа;#pragma pack
менее мелкозернистый, чем атрибуты: он не может применяться только к нескольким членам структуры. На практике, однако, это редко бывает проблемой, поскольку вам редко нужны разные настройки выравнивания и упаковки для членов одной и той же структуры.В очень сжатом виде #pragma pack(n)
примерно эквивалентен __attribute__((packed,aligned(n)))
: он определяет как упаковку (уплотняющие структуры для целей экономии памяти), так и минимальное выравнивание. Следовательно, n
(минимальное выравнивание) на прагме.
В принципе, #pragma pack
можно эмулировать с использованием атрибутов GCC, но не наоборот, из-за более тонкого управления, заданного атрибутами.
Вот пример, который вы можете протестировать на GCC: первое определение использует #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\n", offsetof(struct st, d));
printf("offsetof(struct st2, d) = %zu\n", offsetof(struct st2, d));
printf("offsetof(struct st, e) = %zu\n", offsetof(struct st, e));
printf("offsetof(struct st2, e) = %zu\n", offsetof(struct st2, e));
}
В этом примере GCC выдает предупреждение: ‘packed’ attribute ignored for field of type ‘char’
. В самом деле, более кратким и правильным решением является применение packed
ко всей структуре (как это сделал @Hagai), что эквивалентно 1. Обратите внимание, однако, что вы не можете просто применить aligned
ко всей структуре: поведение не эквивалентно применению aligned
для каждого поля отдельно.
Обратите внимание, что если вы комбинируете оба (прагма + атрибуты) в одном и том же определении структуры, алгоритм является более сложным, поскольку он должен учитывать несколько ограничений, что приводит к некоторым вычислениям min
/max
между (1 ) выравнивание, заданное #pragma pack
, (2) минимальное выравнивание типа члена и (3) aligned
атрибуты, объявленные в поле (если есть).
1 Из Документация GCC:
Указание упакованного атрибута для типов struct и union эквивалентно заданию упакованного атрибута для каждой из элементов структуры или объединения.