重新定义typedef

我可能做错了,这是一个很大的问题,为什么它在一个编译器中工作而不是另一个编译器。

我有一个大型的C应用程序,我试图遵循不包括其他头文件中的头文件的样式。 相反,使用前向声明; 因此我正在尝试以下方面。

// in Ah typedef struct A_ A; typedef struct B_ B; struct A_ { double a; B *b; }; // in Bh typedef struct B_ B; struct B_ { int c; }; // in Ch typedef struct A_ A; typedef struct B_ B; void function_do_something(A*, B*); // in Cc #include "Ah" #include "Bh" #include "Ch" void function_do_something(A* a, B* b) { ... } 

这个范例在Ubuntu 11.10 gcc中编译和运行 – 但是它给OpenSUSE gcc中的编译器错误提供了“重新定义typedef”。

我一直在Ubunutu进行开发,所以没有意识到这种范式可能是错误的。 是不是这是完全错误的,Ubuntu的gcc太漂亮了?

我对此感到惊讶,因为我很确定在同一范围内重新声明相同的typedef在C ++中是合法的,但显然它在C中是不合法的。

首先,typedef名称没有链接:

ISO / IEC 9899:1999 + TC3 6.2.6 / 6:

以下标识符没有链接:声明为对象或函数以外的任何标识符的标识符[…]

和6.7 / 3:

如果标识符没有链接,则除了6.7.2.3中指定的标记之外,标识符(在声明符或类型说明符中)的声明不应超过一个具有相同作用域和相同名称空间的声明。

因此,您需要确保每个typedef声明仅在每个转换单元的文件范围内出现一次。

缺少一个成语。 前向声明独立于定义,因此它们应位于单独的头文件中。

 // a_fwd.h #ifndef A_FWD_H #define A_FWD_H typedef struct A_ A; #endif // ah #ifndef A_H #define A_H #include "a_fwd.h" struct A_ { }; #endif 

现在,按任何顺序包含任何标题始终是安全的。


对任何事物都有两个定义是违法的。 typedef是一个定义,而不仅仅是一个声明,因此一个编译器在允许冗余方面非常宽松。

就像样式一样,我会将typedef放在struct之后。 即:

 struct B_ { int c; }; typedef struct B_ B; 

那样你就说:“这里是B_,现在我想把它称为B”。 可能是相反的方式愚弄编译器中的东西。

ubuntu编译器过于柔软; 你不能两次输入相同的东西。 在您引用的样式中,包含的顺序很重要,通常在头文件或文档中作为注释提及。 在这种情况下,您将拥有:

 //Ah typedef struct AA; struct A { double a; B* b; }; // Bh typedef struct BB; struct B { int c; }; // Ch void function_do_something(A*, B*); // Cc #include "Bh" #include "Ah" #include "Ch" void function_do_something(A* a, B* b){ ... } 

您可能会注意到,在循环依赖的情况下,这将变得混乱。

您正在通过在几个头文件中写入相同的语句来重新定义A和B. 一种解决方案是从Ah和Bh中删除A和B的typedef并按原样使用你的Ch。

正如其他人已经说过的那样,你不能在C中重新定义类型。这个错误主要表明可能存在循环包含或其他逻辑缺陷。 为避免这种情况,最佳做法是锁定包含文件,即

 #ifndef __HEADER_H__ #define __HEADER_H__ // Your code goes here #endif 

这种方式将通过此锁省略不必要的包含。
在您的示例中,您需要在A中包含B,在C中包含A.包括C中的B将不起作用并且将满足编译器

你定义了多次同样的事情。

您可以将它分布在多个头文件中,只需要确保在定义struct _A之前看到了一些B.

此代码有效:

 #include  typedef struct _B B; typedef struct _A A; struct _A { double a; B *b; }; struct _B { int c; }; void function_do_something(A* a, B* b) { printf("a->a (%f) b->c (%d)\n", a->a, b->c); } int main() { A a; B b; aa = 3.4; bc = 34; function_do_something(&a, &b); return 0; } 

输出:

 > ./x a->a (3.400000) b->c (34) 

编辑 :更新为C

编辑2 :传播到多个头文件

BH:

 #ifndef B_H #define B_H struct _B { int c; }; #endif 

啊:

 #ifndef A_H #define A_H typedef struct _B B; struct _A { double a; B *b; }; typedef struct _A A; #endif 

main.c中:

 #include  #include "ah" #include "bh" void function_do_something(A* a, B* b) { printf("a->a (%f) b->c (%d)\n", a->a, b->c); } int main() { A a; B b; aa = 3.4; bc = 34; function_do_something(&a, &b); return 0; }