重新定义typedef

BrT*_*BrT 19 c gcc typedef

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

我有一个大型的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声明仅在每个翻译单元的文件范围内出现一次.

  • 从C11开始(在此答案之前8个月!),允许将typedef重新定义为相同的东西.对于这种情况,在6.7/3中添加了一个例外 (5认同)

Pot*_*ter 6

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

// 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是一个定义,而不仅仅是一个声明,因此一个编译器在允许冗余方面非常宽松.