packed
属性应放在声明中的何处?C2x(C++风格(和旧GNU属性的使用有什么区别吗?
鉴于GCC文档不是很清楚,我开发了以下测试程序作为实验答案:
#include <stdio.h>
struct s {
char a;
long b;
char c;
} s_, s__;
// warning: 'packed' attribute ignored [-Wattributes]
__attribute__((packed)) struct t {
char a;
long b;
char c;
} t_, t__;
// warning: 'packed' attribute ignored [-Wattributes]
[[gnu::packed]] struct ttt {
char a;
long b;
char c;
} ttt_, ttt__;
struct __attribute__((packed)) u {
char a;
long b;
char c;
} u_, u__;
struct [[gnu::packed]] uuu {
char a;
long b;
char c;
} uuu_, uuu__;
// error: expected identifier or '(' before '{' token
/*
struct v __attribute__((packed)) {
char a;
long b;
char c;
} v_, v_;
*/
// error: expected identifier or '(' before '{' token
/*
struct vvv [[gnu::packed]] {
char a;
long b;
char c;
} vvv_, vvv__;
*/
struct w {
char a;
long b;
char c;
} __attribute__((packed)) w_, w__;
// warning: 'packed' attribute ignored for type 'struct www' [-Wattributes]
struct www {
char a;
long b;
char c;
} [[gnu::packed]] www_, www__;
// warning: 'packed' attribute ignored [-Wattributes]
struct x {
char a;
long b;
char c;
} x_ __attribute__((packed)), x__;
// warning: 'packed' attribute ignored [-Wattributes]
struct xxx {
char a;
long b;
char c;
} xxx_ [[gnu::packed]], xxx__;
// warning: 'packed' attribute ignored [-Wattributes]
struct y {
char a;
long b;
char c;
} y_, __attribute__((packed)) y__;
// error: expected identifier or '(' before '[' token
/*
struct yyy {
char a;
long b;
char c;
} yyy_, [[gnu::packed]] yyy__;
*/
// warning: 'packed' attribute ignored [-Wattributes]
struct z {
char a;
long b;
char c;
} z_, z__ __attribute__((packed));
// warning: 'packed' attribute ignored [-Wattributes]
struct zzz {
char a;
long b;
char c;
} zzz_, zzz__ [[gnu::packed]];
int main(void)
{
printf("s: %2zu; s_: %2zu; s__: %2zunn", sizeof(struct s), sizeof(s_), sizeof(s__));
printf("t: %2zu; t_: %2zu; t__: %2zun", sizeof(struct t), sizeof(t_), sizeof(t__));
printf("ttt: %2zu; ttt_: %2zu; ttt__: %2zunn", sizeof(struct ttt), sizeof(ttt_), sizeof(ttt__));
printf("u: %2zu; u_: %2zu; u__: %2zun", sizeof(struct u), sizeof(u_), sizeof(u__));
printf("uuu: %2zu; uuu_: %2zu; uuu__: %2zunn", sizeof(struct uuu), sizeof(uuu_), sizeof(uuu__));
puts("v: -");// printf("v: %2zu; v_: %2zu; v__: %2zun", sizeof(struct v), sizeof(v_), sizeof(v__));
puts("vvv: -n");// printf("vvv: %2zu; vvv_: %2zu; vvv__: %2zun", sizeof(struct vvv), sizeof(vvv_), sizeof(vvv__));
printf("w: %2zu; w_: %2zu; w__: %2zun", sizeof(struct w), sizeof(w_), sizeof(w__));
printf("www: %2zu; www_: %2zu; www__: %2zunn", sizeof(struct www), sizeof(www_), sizeof(www__));
printf("x: %2zu; x_: %2zu; x__: %2zun", sizeof(struct x), sizeof(x_), sizeof(x__));
printf("xxx: %2zu; xxx_: %2zu; xxx__: %2zunn", sizeof(struct xxx), sizeof(xxx_), sizeof(xxx__));
printf("y: %2zu; y_: %2zu; y__: %2zun", sizeof(struct y), sizeof(y_), sizeof(y__));
puts("yyy: -n");// printf("yyy: %2zu; yyy_: %2zu; yyy__: %2zunn", sizeof(struct yyy), sizeof(yyy_), sizeof(yyy__));
printf("z: %2zu; z_: %2zu; z__: %2zun", sizeof(struct z), sizeof(z_), sizeof(z__));
printf("zzz: %2zu; zzz_: %2zu; zzz__: %2zun", sizeof(struct zzz), sizeof(zzz_), sizeof(zzz__));
return 0;
}
cc -Wall -Wextra -o packed packed.c
给出了我在上面评论的警告和错误。我不得不注释掉一些代码以使其编译。
$ ./packed
s: 24; s_: 24; s__: 24
t: 24; t_: 24; t__: 24
ttt: 24; ttt_: 24; ttt__: 24
u: 10; u_: 10; u__: 10
uuu: 10; uuu_: 10; uuu__: 10
v: -
vvv: -
w: 10; w_: 10; w__: 10
www: 24; www_: 24; www__: 24
x: 24; x_: 24; x__: 24
xxx: 24; xxx_: 24; xxx__: 24
y: 24; y_: 24; y__: 24
yyy: -
z: 24; z_: 24; z__: 24
zzz: 24; zzz_: 24; zzz__: 24
结论:
与对齐属性不同,它只适用于类型,而不适用于变量。变量被压缩iff[1]其类型被压缩。这是有道理的;否则,无法将一个变量分配给同一类型的另一个变量。
C2x(C++样式(属性只能位于struct
关键字和struct标记之间。
旧的GNU样式属性可以放在C2x的位置,也可以放在右大括号之后。
[1]:
$ wtf is iff
IFF: if and only if