Подтвердить что ты не робот

Какая разница между "#pragma pack" и "__attribute __ ((aligned))"

Например:

#pragma pack(L1_CACHE_LINE)
struct A {
  //...
};
#pragma pack()

A a;

и

struct A {
  //...
};

A a __attritube__((aligned(L1_CACHE_LINE)))

Какая разница между thwm?

Спасибо заранее!

4b9b3361

Ответ 1

Пакет #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 байтами, но не будет выравнивать другую переменную таким же образом.

Ссылка:

Ответ 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 эквивалентно заданию упакованного атрибута для каждой из элементов структуры или объединения.