C中struct和function之间的循环依赖

问题描述

我有以下文件

A.h

#ifndef __A_H_
#define __A_H_

#include <B.h> // contains foo_t
typedef struct {
     foo_t foo;
     ...
} baz_t;

#endif

B.h

#ifndef __B_H_
#define __B_H_

#include <A.h> // contains baz_t
typedef struct {
     ...
} foo_t;

extern int useful_func(baz_t d);

#endif

当我编译此B.h时,他拒绝编译抱怨error: unkNown type name 'baz_t'

我假设此错误是由于两个文件间的循环依赖性所致。但是我想知道如何转发声明baz_t解决这个问题?我找到了与结构之间的循环依赖关系有关的答案。但是我不确定如何解决这个问题。我希望在这里提供一些帮助。我正在寻找严格的C99解决方案。

编辑

  1. 我以前忘了提及这一点,但是我已经使用过包含卫兵。
  2. 用户KamilCuk建议的一个非常明显的解决方案是将useful_func移至A.h。我也遇到过这种情况,但是不幸的是,软件组织明智的useful_func属于B.h。这个问题也可能反映出设计不佳。

解决方法

您可以如下使用前向声明:

Course

然后在B.h上正常使用

也就是说,如果您在用作接口的第三个标头上定义所有内容,则可以避免循环依赖。这样会更清洁,但并非总是可能。

,

通常,将传递指向结构的指针,而不是按值传递它们。如果可以接受,那么事情就很容易了,因为C编译器将接受一个声明:

void doSomethingWithAFoo(struct foo *it);

,不考虑他们是否对struct foo有任何定义。确实,编译器甚至会接受 definitions 之类的函数:

void doSomethingWithAFooTwice(struct foo *it)
{
  doSomethingWithAFoo(it);
  doSomethingWithAFoo(it);
}

无需知道或关心是否定义struct foo,在何处或如何进行定义。

请注意,使用struct tag语法而不是typedef名称的优势在于,使用struct标记语法的原型不需要声明或定义不能多次无害地声明的任何内容。