Jaka jest różnica między "# pragma pack " a " attribute ((aligned))"

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

A a;

I

struct A {
  //...
};

A a __attritube__((aligned(L1_CACHE_LINE)))
Jaka jest różnica między nimi?
Author: hellow, 2013-01-06

2 answers

Pakiet # pragma (Byte-alignment) powoduje, że każdy element struktury jest określony przez wejście Byte-alignment lub na ich naturalnej granicy wyrównania, w zależności od tego, która z tych wartości jest mniejsza.

__attribute__((aligned(byte-alignment))) wpływa na minimalne wyrównanie zmiennej (lub pola struct, jeśli jest określone w strukturze)

Uważam, że poniższe są równoważne

#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()

Gdzie a __attritube__((aligned(L1_CACHE_LINE))) będzie ubezpieczać u_int32_t a wewnątrz struct A będzie wyrównany z 2 bajtem, ale nie będzie wyrównywał drugiej zmiennej w tym samym sposób.

Odniesienie:

  1. http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Fcompiler%2Fref%2Frnpgpack.htm
  2. http://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/attributes-variables.html
 14
Author: Hagai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-06 06:32:45

#pragma pack jest składnią Microsoft, która została przeniesiona do GCC ze względu na kompatybilność.

__attribute__((aligned)) jest składnią specyficzną dla GCC (nieobsługiwaną przez MSVC).

Oto podsumowanie różnic:

  • #pragma pack (i warianty) jest bardziej zwięzły i reprezentuje zarówno atrybuty packed i aligned w składni GCC (patrz przykład poniżej);
  • #pragma pack stosuje się do każdej definicji struktury umieszczonej po miejscu, w którym została wstawiona (lub do czasu nadpisania innej #pragma pack to), podczas gdy GCC __attribute__ S są definiowane lokalnie do typu;
  • #pragma pack jest mniej drobnoziarnista niż atrybuty: nie może być stosowana tylko do kilku elementów struktury. W praktyce jednak rzadko jest to problemem, ponieważ rzadko będziesz potrzebował różnych ustawień wyrównywania i pakowania dla członków tej samej struktury.

W bardzo zwięzły sposób, {[10] } jest mniej więcej równoważne __attribute__((packed,aligned(n))): definiuje zarówno pakowanie (zagęszczanie struktur dla celów oszczędzania pamięci), jak i minimalne wyrównanie . Stąd n (Minimalne wyrównanie) na pragmie.

W zasadzie, #pragma pack można emulować używając atrybutów GCC, ale nie odwrotnie, ze względu na lepszą kontrolę nad atrybutami.

Oto przykład, który możesz przetestować na GCC: pierwsza definicja używa #pragma pack, a druga używa atrybutów. Układ jest taki sam w obu przypadkach.

#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 emituje ostrzeżenie na tym przykładzie: ‘packed’ attribute ignored for field of type ‘char’. Rzeczywiście, bardziej zwięzłym i właściwym rozwiązaniem jest apply packed to the whole struct (as @Hagai did), which is equivalent1. Należy jednak pamiętać, że nie można po prostu zastosować aligned do całej struktury: zachowanie jest , a nie równoważne zastosowaniu aligned do każdego pola osobno.

Zauważ, że jeśli połączysz oba (pragma + atrybuty) w tej samej definicji struktury, algorytm jest bardziej złożony, ponieważ musi przestrzegać kilku ograniczeń, które skutkują pewnymi min/max obliczenia między (1) wyrównanie podane przez #pragma pack, (2) Minimalne wyrównanie typu member oraz (3) aligned atrybuty zadeklarowane w polu (jeśli występują).

1 Z dokumentacji GCC :

Określenie atrybutu packed dla typów struct i union jest równoważne określeniu atrybutu packed dla każdej struktury lub członków Unii.

 15
Author: anol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-31 08:15:08