简体   繁体   English

定义前是否允许 typedef

[英]Is typedef allowed before definition

Minimum code:最低代码:

// foo.h

typedef struct foo_s foo_t;

struct foo_s {
  foo_t* next;
};

iwyu insists I forward declare struct foo_s before I typedef it to foo_t . iwyu坚持我在typedef到 foo_t 之前转发声明struct foo_s foo_t

Output: Output:

$ iwyu -c foo.h 

foo.h should add these lines:
struct foo_s;

foo.h should remove these lines:

The full include-list for foo.h:
struct foo_s;
---

This is true across different versions of iwyu , including newer versions with -Xiwyu --no_fwd_decls added.这适用于不同版本的iwyu ,包括添加了-Xiwyu --no_fwd_decls的较新版本。

Is this a mistake in iwyu or does the C standard want me to define the type before the typedef ?这是iwyu的错误还是C标准要我在typedef之前定义类型?

does the C standard want me to define the type before the typedef ? C 标准是否希望我在typedef之前定义类型?

It does not.它不是。 The standard verbiage is as follows标准用语如下

6.7.2.3 Tags 6.7.2.3 标签

7 A declaration of the form 7表格声明

 struct-or-union identifier;

specifies a structure or union type and declares the identifier as a tag of that type.指定结构或联合类型并将标识符声明为该类型的标记。

8 If a type specifier of the form 8如果一个类型说明符的形式

 struct-or-union identifier

occurs other than as part of one of the above forms, and no other declaration of the identifier as a tag is visible, then it declares an incomplete structure or union type, and declares the identifier as the tag of that type.除了作为上述 forms 之一的一部分发生之外,并且没有其他标识符声明为标记可见,则它声明一个不完整的结构或联合类型,并将标识符声明为该类型的标记。

So your original pair of declarations has well-defined behavior.因此,您的原始声明对具有明确定义的行为。 The declaration for the structure is implicitly added into the translation unit at the point you define the type alias, and then completed afterward.结构的声明在您定义类型别名时隐式添加到翻译单元中,然后完成。 The fact that the tool does not allow it may be due to a bug, a limitation of the tool, or perhaps an attempt to enforce a particular coding style.该工具不允许它的事实可能是由于错误,工具的限制,或者可能是试图强制执行特定的编码风格。


There is one point in favor of the style that the tool may try to enforce, and it has to do with the C notion of scope.有一点支持该工具可能会尝试强制执行的样式,它与 scope 的 C 概念有关。 Specifically, function parameter list scope.具体来说,function参数列表scope。 As an example, see this Q&A and refer to this short example例如, 请参阅此问答并参考此简短示例

void bar(struct foo);

struct foo {
    char c;
};

void bar(struct foo f) {}

It so happens that the first declaration of bar is declared with a type that is unique to its parameter list.碰巧bar的第一个声明是使用其参数列表唯一的类型声明的。 The initial declaration of struct foo is not the same type as the one used in the later function definition. struct foo的初始声明与后面的 function 定义中使用的类型不同。 As such, the code will not compile by a conforming C compiler.因此,代码不会被符合标准的 C 编译器编译。 Declaring the structure on its own line ahead of the first function declaration fixes this problem.在第一个 function 声明之前在自己的行上声明结构可以解决此问题。

This C11 Draft Standard makes it quite clear that you can 'forward declare' a typedef struct... , by way of an example that is very similar to your code:这个C11 Draft Standard通过与您的代码非常相似的示例非常清楚地表明您可以“转发声明” typedef struct...

6.7.2.3 Tags 6.7.2.3 标签
... ...
11 The following alternative formulation uses the typedef mechanism: 11 以下替代公式使用typedef机制:

 typedef struct tnode TNODE; struct tnode { int count; TNODE *left, *right; }; TNODE s, *sp;

It is a bug.这是一个错误。 It seems the typedef for a structure is considered the same way as a typedef for an enumeration.似乎结构的 typedef 被认为与枚举的 typedef 相同。

For enumerations you may not use an incomplete type in a typedef definition对于枚举,您不能在 typedef 定义中使用不完整的类型

From the C Standard (6.7.2.3 Tags)来自 C 标准(6.7.2.3 标签)

3 A type specifier of the form 3 形式的类型说明符

enum identifier 

without an enumerator list shall only appear after the type it specifies is complete.没有枚举器列表只能在它指定的类型完成后出现。

So for example such a typedef所以例如这样一个typedef

typedef enum E AnotherE;

enum E { N };

is invalid while this typedef此 typedef 时无效

enum E { N };

typedef enum E AnotherE;

is valid.已验证。

For structures you may use an incomplete type in a typedef definition.对于结构,您可以在 typedef 定义中使用不完整的类型。

8 If a type specifier of the form 8 如果一个类型说明符的形式

struct-or-union identifier

occurs other than as part of one of the above forms, and no other declaration of the identifier as a tag is visible, then it declares an incomplete structure or union type, and declares the identifier as the tag of that type.除了作为上述 forms 之一的一部分发生之外,并且没有其他标识符声明为标记可见,则它声明一个不完整的结构或联合类型,并将标识符声明为该类型的标记。

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

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