我可能做错了,这是一个很大的问题,为什么它在一个编译器中工作而不是另一个编译器.
我有一个大型的C应用程序,我试图遵循不包括其他头文件中的头文件的样式.相反,使用前向声明; 因此我正在尝试以下方面.
// in A.h
typedef struct A_ A;
typedef struct B_ B;
struct A_ {
double a;
B *b;
};
// in B.h
typedef struct B_ B;
struct B_ {
int c;
};
// in C.h
typedef struct A_ A;
typedef struct B_ B;
void function_do_something(A*, B*);
// in C.c
#include "A.h"
#include "B.h"
#include "C.h"
void function_do_something(A* a, B* b) {
...
}
Run Code Online (Sandbox Code Playgroud)
这个范例在Ubuntu 11.10 gcc中编译和运行 - 但是它给OpenSUSE gcc中的编译器错误提供了"重新定义typedef".
我一直在Ubunutu进行开发,所以没有意识到这种范式可能是错误的.是不是这是完全错的,Ubuntu的gcc太漂亮了?
CB *_*ley 25
我对此感到惊讶,因为我很确定在同一范围内重新声明相同的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
// a.h
#ifndef A_H
#define A_H
#include "a_fwd.h"
struct A_ {
};
#endif
Run Code Online (Sandbox Code Playgroud)
现在,以任何顺序包含任何标题始终是安全的.
对任何事物都有两个定义是违法的.typedef是一个定义,而不仅仅是一个声明,因此一个编译器在允许冗余方面非常宽松.