【问题标题】:C circular dependency with headers带有标头的 C 循环依赖
【发布时间】:2018-12-06 18:15:42
【问题描述】:

我正在从事一个项目,我必须遵循文件组织指南,但无法编译。

为了简化它,我有一个 main.h,我必须在其中定义 bool 和一些符号:

#ifndef main_h
#define main_h

#include <stdio.h>
#include "test.h"

typedef unsigned char    bool;
#define TRUE  1
#define FALSE 0

#endif /* main_h */

然后 main.c 必须使用类型“num_seconds_t”和函数“test()”,这两者都必须位于与 main 不同的文件中。

所以我有我的 test.h:

#ifndef test_h
#define test_h

#include <stdio.h>
#include "main.h"

typedef int32_t num_seconds_t;
bool test(num_seconds_t var);

#endif /* test_h */

还有我的 test.c:

#include "test.h"

bool test(num_seconds_t var){
    num_seconds_t test = var;
    return TRUE;
}

我认为 main.c 不会对这个问题产生任何影响。

错误在我的 test.h 文件中声明了未知类型“bool”,我有点理解为什么当它在 main.h 中点击“test.h”的包含时,它会在它之前开始遍历该文件在 main.h 中定义了 bool,然后由于 main.h 在 test.h 中点击“#include”main.h”时具有“#ifndef main_h”,因此它会跳过此并继续读取,因此 bool 直到测试之后才被定义.h 已完成读取。

我不确定我的理解是否正确,但解决此问题的正确方法是什么。通过简单地将“#include”test.h“”移动到 bool 的定义之后,它将编译,但在我的大项目中,我有许多文件交织在一起,并且协调包含这些文件的顺序将非常困难,如果不是不可能的话。

谢谢

【问题讨论】:

  • 为什么你的主标题中有#include "test.h"?那里似乎没有必要
  • 将你的 typedef 移动到第三个文件中,并将其包含在 test 和 main 中。
  • 在这种情况下,您应该在 main.c 文件中包含 test.h,而不是标题 - 仅在您实际需要的地方包含标题可以解决很多问题
  • @VladRusu 它是项目的一部分,我不允许在其他任何地方定义类型。我同意这样做会更合乎逻辑
  • 旁白:为什么要创建typedef unsigned char bool; 而不是使用C 布尔类型_Boolbool via #include `?

标签: c


【解决方案1】:

我将提出 3 个解决方案:

1) 你最好的选择是不要 main.h 中的 #include test.h,因为你不需要在 main.h 中的 test.h 中定义的任何东西(你确实需要来自 test.h 中的 @987654327 的东西@,所以 test.h 应该是 #includeed in main.c)。这通常是一种很好的做法,如 cmets 中所述(您不想 #include 不需要的东西)。

2) 您的第二个最佳选择是将内容从 test.hmain.h 移动到另一个文件。在这种情况下,您需要将 typedefs 和 #defines 移动到另一个文件,如下所示:

typedef unsigned char bool;
#define TRUE  1
#define FALSE 0
typedef int32_t num_seconds_t;

然后将此文件包含在main.htest.h 中(或仅包含在test.h 中,因为`main.h 不需要这些类型定义)。

3) 您最后也是最糟糕的选择是仔细选择包含内容的顺序。这是你最糟糕的选择,因为它在大型项目中变得非常笨拙,但我还是会展示它。

让所有其他文件保持不变并执行:

// main.c

#include test.h

因为 main.c 中的唯一包含将解决您的问题。当你尝试编译它时,只有test.h 将在main.c 中被#includeed。然后这将包括main.h,它具有test.h 所需的类型定义。 main.h 不会再次包含 test.h,因为它已经包含在内。这没关系,因为main.h 实际上并不需要test.h

您还可以将#include 中的main.h 移动到您的typedef 下方,并将main.h 包含在main.c 中。然而,正如我所提到的,选项 3 不是一个好的选择。

您确实应该将选项 1 和 2 结合起来(一般来说,不只是针对这个项目)。

【讨论】:

  • 我认为您列表中的选项 2 是此已发布问题的最佳选择。这意味着要管理的包含文件更少。
  • @RichardChambers 我认为总的来说,将所有 typedef 放在一个地方确实有助于大型项目的结构(并且没有这个比包含太多更难修复)。对于这个问题,我认为您是对的,但会编辑。
  • 虽然值得注意的是,OP 的要求基本上使最佳选择 (#2 imo) 成为不可能。
  • @zzxyz 是的,我认为将它们拉出到单独的文件中通常是正确的解决方案,但由于 OP 的限制,这是不可能的。因此,不包括额外的东西是 OP 恕我直言的最佳选择。
  • @RichardChambers 阅读 OPs 帖子,特别注意他的全部大写短语。他的要求是荒谬的(我敢肯定,这不是他自己的过错)。中的cmets?澄清一下。
猜你喜欢
  • 2011-07-11
  • 1970-01-01
  • 2012-02-19
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多