#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.