我可能做错了,这是一个很大的问题,为什么它在一个编译器中工作而不是另一个编译器。
我有一个大型的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太漂亮了?
答案 0 :(得分:21)
我对此感到惊讶,因为我很确定在同一范围内重新声明相同的typedef在C ++中是合法的,但显然它在C中是不合法的。
首先,typedef名称没有链接:
ISO / IEC 9899:1999 + TC3 6.2.6 / 6:
以下标识符没有链接:声明为除。之外的任何标识符 对象或函数[...]
和6.7 / 3:
如果标识符没有链接,则标识符的声明不得超过一个 (在声明符或类型说明符中)具有相同的作用域和相同的名称空间,除外 对于6.7.2.3中指定的标签。
因此,您需要确保每个typedef声明仅在每个翻译单元的文件范围内出现一次。
答案 1 :(得分:5)
缺少一部成语。前向声明独立于定义,因此它们应位于单独的头文件中。
// 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是一个定义,而不仅仅是一个声明,因此一个编译器在允许冗余方面非常宽松。
答案 2 :(得分:1)
就风格问题而言,我会将typedef放在struct之后。即:
struct B_ {
int c;
};
typedef struct B_ B;
你这样说:“这里是B_,现在我想把它称为B”。可能反过来愚弄编译器中的某些东西。
答案 3 :(得分:1)
ubuntu编译器过于柔软;你不能两次输入相同的东西。在您引用的样式中,包含的顺序很重要,通常在头文件或文档中作为注释提及。在这种情况下,您将拥有:
//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){ ... }
您可能会注意到,在循环依赖的情况下,这会变得混乱。
答案 4 :(得分:0)
您正在通过在多个头文件中写入相同的语句来重新定义A和B.一种解决方案是从A.h和B.h中删除A和B的typedef
并按原样使用C.h。
答案 5 :(得分:0)
正如其他人已经说过的那样,你不能在C中重新定义类型。这个错误主要表明可能存在循环包含或其他逻辑缺陷。为避免这种情况,最佳做法是锁定包含文件,即
#ifndef __HEADER_H__
#define __HEADER_H__
// Your code goes here
#endif
这种锁将省略不必要的包含 在您的示例中,您需要在A中包含B,在C中包含A.包括C中的B将无效并且将满足编译器
答案 6 :(得分:-3)
您定义了多次相同的事情。
你可以将它传播到多个头文件中,只需要确保在定义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 :传播到多个头文件
b.h:
#ifndef B_H
#define B_H
struct _B {
int c;
};
#endif
A.H:
#ifndef A_H
#define A_H
typedef struct _B B;
struct _A {
double a;
B *b;
};
typedef struct _A A;
#endif
main.c中:
#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;
}