重新定义typedef

时间:2011-12-03 12:29:54

标签: 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) {
    ...
}

这个范例在Ubuntu 11.10 gcc中编译和运行 - 但是它在OpenSUSE gcc中给出了编译器错误,它说“重新定义了typedef”。

我一直在Ubunutu进行我的开发,因此没有意识到这种范式可能是错误的。是不是这是完全错误的,Ubuntu的gcc太漂亮了?

7 个答案:

答案 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;
}