重新定义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; }