简体   繁体   English

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

[英]Why do these C struct definitions give warnings and errors?

Why do these two struct definitions compile fine: 为什么这两个结构定义编译正常:

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

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

While this one gives a warning: 虽然这个发出警告:

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


warning: ‘packed’ attribute ignored [-Wattributes]

And this one gives an error and a warning: 这一个给出了错误和警告:

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]

As a novice C programmer, the fact that the last two definitions don't work seems like a fairly arbitrary choice on the parts of the language designers/compiler writers. 作为新手C程序员,最后两个定义不起作用的事实似乎是语言设计者/编译器编写者的一个相当随意的选择。 Is there a reason for this? 是否有一个原因? I'm using gcc 4.7.3. 我正在使用gcc 4.7.3。

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

vs VS

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

In the first you said "consider this anonymous structure, with the attribute packed, that has a member a. then create an alias for this structure, and name that 'bar'". 在第一个你说“考虑这个匿名结构,包含属性,有一个成员a。然后为这个结构创建一个别名,并命名为'bar'”。 The normal syntax for describing a struct without doing it anonymously and having to typedef it is 用于描述结构而不是匿名执行并且必须键入def的正常语法是

struct bar { int a; };

in the second declaration you said "consider this anonymous structure, that has a member a. then create an alias for this structure, and name that 'baz who is packed'". 在第二个声明中你说“考虑这个匿名结构,它有一个成员a。然后为这个结构创建一个别名,并命名'baz who packed'”。

It doesn't work because you're trying to apply the attribute to the alias in a typedef, not to the structure definition. 它不起作用,因为您尝试将该属性应用于typedef中的别名,而不是结构定义。

typedef <entity> <alias>;

I would advise putting on a hit on whomever suggested you use the "typedef" syntax for describing structs :) 我会建议你使用“typedef”语法来描述结构:)

The reason that it works in the first two instances is because __attribute__((packed)) can only be applied to a struct , union or enum . 它在前两个实例中工作的原因是因为__attribute__((packed))只能应用于structunionenum In the first example, you're declaring a struct called foo , in the second you are declaring a struct called bar . 在第一个示例中,您将声明一个名为foostruct ,在第二个示例中,您将声明一个名为barstruct In this second example, typedef converts a declaration of a variable into a declaration of a type. 在第二个示例中, typedef将变量的声明转换为类型的声明。

Your third example is declaring a variable called baz and trying to declare it as packed. 你的第三个例子是声明一个名为baz的变量并尝试将其声明为packed。 Since packing info is attached to the type, not an instance, this makes no sense, and the compiler ignores it. 由于打包信息附加到类型而不是实例,这没有任何意义,编译器会忽略它。

Here are details on how attributes work in gcc . 以下是有关属性如何在gcc中工作的详细信息

You really shouldn't be even using packed unless you know exactly what you are doing. 除非你确切知道自己在做什么,否则你真的不应该使用包装。 For one thing, __attribute__ is not standard C. If is a gcc extension and so won't work with any other compiler. 首先, __attribute__不是标准C.如果是gcc扩展,那么不能与任何其他编译器一起使用。

For another, there are very few situations where it is actually needed. 另一方面,实际需要的情况很少。 In your code above, for instance, it is a no-op even in the first two instances as packing removes space between members, and you've only got one member in each struct . 例如,在上面的代码中,即使在前两个实例中它也是一个无操作,因为打包会删除成员之间的空间,并且每个struct只有一个成员。 The reason that packing structures isn't the default is because common datatypes just work better when aligned on a certain boundary. 打包结构不是默认值的原因是因为常见数据类型在特定边界上对齐时效果更好。 For instance, access to an int will perform better if aligned on a memory location that is a multiple of four. 例如,如果在4的倍数的内存位置上对齐,则对int访问将更好。 See the wiki entry on data structure alignment for more information . 有关更多信息,请参阅有关数据结构对齐的wiki条目

The keyword __attribute__((packed)) applies to struct . 关键字__attribute__((packed))适用于struct

In

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

typedef associates baz with the struct - the attributes comes after, and applies to nothing - gcc ignores it. typedef将 baz与结构相关联 - 属性在后面,并且不适用于任何内容 - gcc忽略它。 To fix this, allow typedef to associate the whole struct declaration, including the attribute , by placing baz after the attribute: 为了解决这个问题,让typedef的整个结构声明,由属性后,将联想巴兹 ,包括属性

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

In the 2nd example, the struct declaration is wrong 在第二个例子中, struct声明是错误的

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

as quz should appear after the attribute: 因为quz应出现在属性之后:

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

It is usually better to let the compiler optimizes the structure and align the inner elements in memory in a way the CPU processes them more efficiently. 通常最好让编译器优化结构并以CPU更有效地处理它们的方式对齐内存中的内部元素。

Packing a structure, however, may be important at times when building a data structure that has to be packed, in order to cope, for instance, with a driver demands. 包装的结构,但是,建立时必须要打包的数据结构,为了应对,例如,与驱动器的需求有时可能很重要。

This is a rather odd question because it's all very well explained in the manual. 这是一个相当奇怪的问题,因为它在手册中都有很好的解释。 However to there isn't anything arbitrary about it, you're just not exploring the complete use of this built-in keyword: 然而,对于它没有任何武断,你只是没有探索这个内置关键字的完整使用:

__attribute__(()) is a general purpose gcc extension. __attribute__(())是一个通用的gcc扩展。 There are function attributes, type attributes and variable attributes. 有功能属性,类型属性和变量属性。

Where you place the word __attribute__ determines what it applies to. 放置__attribute__确定它适用的内容。 You could potentially have several __attribute__ s in a given declaration so it's not arbitrary to make some of it syntactically unacceptable for easier internal parsing. 您可能在给定的声明中有几个__attribute__ ,因此,为了更容易进行内部解析,使其中某些语法不可接受并不是任意的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM