为什么这些C结构定义会发出警告和错误?

gsi*_*011 4 c gcc struct

为什么这两个结构定义编译正常:

struct foo {
    int a;
} __attribute__((packed));

typedef struct __attribute__((packed)) {
    int a;
} bar;
Run Code Online (Sandbox Code Playgroud)

虽然这个发出警告:

typedef struct {
    int a;
} baz __attribute__((packed));


warning: ‘packed’ attribute ignored [-Wattributes]
Run Code Online (Sandbox Code Playgroud)

这一个给出了错误和警告:

typedef struct qux __attribute__((packed)) {
    int a;
} qux;

error: expected identifier or ‘(’ before ‘{’ token
warning: data definition has no type or storage class [enabled by default]
Run Code Online (Sandbox Code Playgroud)

作为新手C程序员,最后两个定义不起作用的事实似乎是语言设计者/编译器编写者的一个相当随意的选择.是否有一个原因?我正在使用gcc 4.7.3.

kfs*_*one 6

typedef struct __attribute__((packed)) {
    int a;
} bar;
Run Code Online (Sandbox Code Playgroud)

VS

typedef struct {
    int a;
} baz __attribute__((packed));
Run Code Online (Sandbox Code Playgroud)

在第一个你说"考虑这个匿名结构,包含属性,有一个成员a.然后为这个结构创建一个别名,并命名为'bar'".用于描述结构而不是匿名执行并且必须键入def的正常语法是

struct bar { int a; };
Run Code Online (Sandbox Code Playgroud)

在第二个声明中你说"考虑这个匿名结构,它有一个成员a.然后为这个结构创建一个别名,并命名'baz who packed'".

它不起作用,因为您尝试将该属性应用于typedef中的别名,而不是结构定义.

typedef <entity> <alias>;
Run Code Online (Sandbox Code Playgroud)

我会建议你使用"typedef"语法来描述结构:)


Gor*_*bot 1

它在前两个实例中起作用的原因是因为__attribute__((packed))只能应用于struct,unionenum。在第一个示例中,您声明一个struct被调用的foo,在第二个示例中您声明一个struct被调用的bar。在第二个示例中,typedef将变量声明转换为类型声明。

您的第三个示例是声明一个名为的变量baz并尝试将其声明为打包的。由于打包信息附加到类型而不是实例,因此这是没有意义的,并且编译器会忽略它。

以下是有关属性在 gcc 中如何工作的详细信息

除非你确切地知道自己在做什么,否则你真的不应该使用Packed。一方面,__attribute__它不是标准 C。它是一个gcc扩展,因此不能与任何其他编译器一起使用。

另一方面,真正需要它的情况很少。例如,在上面的代码中,即使在前两个实例中,它也是无操作的,因为打包会删除成员之间的空间,并且每个struct. 打包结构不是默认值的原因是,通用数据类型在特定边界上对齐时效果更好。例如,int如果在四的倍数的内存位置上对齐,对 an 的访问将执行得更好。有关详细信息,请参阅有关数据结构对齐的 wiki 条目