4

最低代码:

// foo.h

typedef struct foo_s foo_t;

struct foo_s {
  foo_t* next;
};

iwyu坚持我struct foo_s在我之前typedef转发声明foo_t

输出:

$ 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;
---

这适用于不同版本iwyu-Xiwyu --no_fwd_decls.

这是一个错误iwyu还是C标准希望我在 ? 之前定义类型typedef

4

3 回答 3

4

C 标准是否要我在 ? 之前定义类型typedef

它不是。标准用语如下

6.7.2.3 标签

7表格声明

      struct-or-union identifier ;

指定结构或联合类型并将标识符声明为该类型的标记。

8如果一个类型说明符的形式

      struct-or-union identifier

除了作为上述形式之一的一部分出现,并且没有其他标识符作为标记的声明是可见的,那么它声明了一个不完整的结构或联合类型,并将标识符声明为该类型的标记。

因此,您的原始声明对具有明确定义的行为。结构的声明在您定义类型别名时隐式添加到翻译单元中,然后完成。该工具不允许它的事实可能是由于错误,工具的限制,或者可能是试图强制执行特定的编码风格。


有一点支持该工具可能会尝试强制执行的样式,这与 C 的范围概念有关。具体来说,函数参数列表范围。例如,请参阅此问答并参考此简短示例

void bar(struct foo);

struct foo {
    char c;
};

void bar(struct foo f) {}

碰巧的是,第一个声明bar是使用其参数列表唯一的类型声明的。的初始声明struct foo与后面函数定义中使用的类型不同。因此,代码不会被符合标准的 C 编译器编译。在第一个函数声明之前在自己的行上声明结构可以解决此问题。

于 2020-05-06T21:56:55.687 回答
1

这个C11 标准草案通过与您的代码非常相似typedef struct...的示例非常清楚地表明您可以“转发声明” a :

6.7.2.3 标签
...
11 以下替代公式使用typedef机制:

typedef struct tnode TNODE;
struct tnode {
    int count;
    TNODE *left, *right;
};
TNODE s, *sp; 
于 2020-05-06T22:02:36.853 回答
0

这是一个错误。似乎结构的 typedef 被认为与枚举的 typedef 相同。

对于枚举,您不能在 typedef 定义中使用不完整的类型

来自 C 标准(6.7.2.3 标签)

3 形式的类型说明符

enum identifier 

没有枚举器列表只能在它指定的类型完成后出现。

所以例如这样一个typedef

typedef enum E AnotherE;

enum E { N };

此 typedef 时无效

enum E { N };

typedef enum E AnotherE;

已验证。

对于结构,您可以在 typedef 定义中使用不完整的类型。

8 如果一个类型说明符的形式

struct-or-union identifier

除了作为上述形式之一的一部分出现,并且没有其他标识符作为标记的声明是可见的,那么它声明了一个不完整的结构或联合类型,并将标识符声明为该类型的标记。

于 2020-05-06T22:05:36.003 回答