[英]redefinition of 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) {
...
}
这个范例在 Ubuntu 11.10 gcc 中编译和运行——但它在 OpenSUSE gcc 中给出了编译器错误,说“重新定义 typedef”。
我一直在 Ubunutu 中进行开发,所以没有意识到这种范式可能是不正确的。 仅仅是因为这是完全错误的并且 Ubuntu 的 gcc 太好了吗?
我对此感到惊讶,因为我相当确定在同一范围内重新声明相同的 typedef 在 C++ 中是合法的,但显然在 2011 标准之前在 C 中是不合法的。
首先,typedef 名称没有链接:
ISO/IEC 9899:1999 + TC3 6.2.6/6:
以下标识符没有链接:声明为对象或函数以外的任何标识符的标识符 [...]
和 6.7/3:
如果标识符没有链接,除了 6.7.2.3 中规定的标签外,在相同的范围和相同的名称空间中,标识符的声明(在声明符或类型说明符中)不得超过一个。
因此,您需要确保每个 typedef 声明在每个翻译单元的文件范围内仅出现一次。
2011 C 标准允许重新声明 typedef 名称。 6.7 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
现在以任何顺序包含任何标题总是安全的。
对任何事物有两个定义是违法的。 typedef 是一个定义,而不仅仅是一个声明,因此一个编译器非常松懈以允许冗余。
就风格而言,我会将 typedef 放在结构之后。 IE:
struct B_ {
int c;
};
typedef struct B_ B;
这样你就会说:“这里是 B_,现在我想把它称为 B”。 可能是相反的方式愚弄了编译器中的某些东西。
ubuntu 编译器过于软; 你不能两次 typedef 相同的东西。 在您引用的样式中,包含的顺序很重要,通常在头文件或文档中作为注释提及。 在这种情况下,您将拥有:
//A.h
typedef struct A A;
struct A {
double a;
B* b;
};
// B.h
typedef struct B B;
struct B {
int c;
};
// C.h
void function_do_something(A*, B*);
// C.c
#include "B.h"
#include "A.h"
#include "C.h"
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 <stdio.h>
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;
a.a = 3.4;
b.c = 34;
function_do_something(&a, &b);
return 0;
}
输出:
> ./x
a->a (3.400000) b->c (34)
编辑:更新为 C
编辑2 :传播到多个头文件
哈:
#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
主文件:
#include <stdio.h>
#include "a.h"
#include "b.h"
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;
a.a = 3.4;
b.c = 34;
function_do_something(&a, &b);
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.