Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
596 views
in Technique[技术] by (71.8m points)

gcc - What is the difference between "#pragma pack" and "__attribute__((aligned))"

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

A a;

and

struct A {
  //...
};

A a __attritube__((aligned(L1_CACHE_LINE)))

What's difference between them?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

#pragma pack is a Microsoft syntax that has been ported to GCC for compatibility reasons.

__attribute__((aligned)) is a GCC-specific syntax (unsupported by MSVC).

Here's a summary of the differences:

  • #pragma pack (and variants) is more concise, and represents both attributes packed and aligned in GCC syntax (see example below);
  • #pragma pack applies to every structure definition placed after where it is inserted (or until another #pragma pack overrides it), while GCC __attribute__s are defined locally to a type;
  • #pragma pack is less fine-grained than attributes: it cannot be applied to only a few members of a struct. In practice, however, this is rarely an issue, since you'll rarely need different alignment and packing settings for the members of a same struct.

In a very concise way, #pragma pack(n) is roughly equivalent to __attribute__((packed,aligned(n))): it defines both packing (compacting structures for memory-saving purposes) and minimal alignment. Hence the n (minimal alignment) on the pragma.

In principle, #pragma pack can be emulated using GCC attributes, but not the other way around, because of the finer control given by attributes.

Here's an example you can test on GCC: the first definition uses #pragma pack and the second one uses attributes. The layout is the same in both cases.

#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));
}

GCC emits a warning on this example: ‘packed’ attribute ignored for field of type ‘char’. Indeed, a more concise and proper solution is to apply packed to the entire struct (as @Hagai did), which is equivalent1. Note, however, that you cannot simply apply aligned to the whole structure: the behavior is not equivalent to applying aligned to each field separately.

Note that, if you combine both (pragma + attributes) in the same structure definition, the algorithm is more complex, because it has to respect several constraints, which result in some min/max computations between (1) the alignment given by #pragma pack, (2) the member type's minimal alignment, and (3) aligned attributes declared in the field (if any).

1 From the GCC documentation:

Specifying the packed attribute for struct and union types is equivalent to specifying the packed attribute on each of the structure or union members.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...