1

我有 2 个必须包含另一个的头文件。

配置.h:

#ifndef CONFIG
#define CONFIG

#include "debug.h"

typedef struct Config_t {
    /* some stuff */
} Config;
#endif

调试.h

#ifndef DEBUG
#define DEBUG

#include "config.h"

void somePrintingFunction(Config* conf);
#endif

这是我得到的错误:

debug.h:错误:未知类型名称“配置”

config.c:警告:函数“somePrintingFunction”的隐式声明

debug.h:错误:未知类型名称“配置”

我猜它在标题声明中循环?


编辑:

修复了合并两个文件以简化项目设计。如果您想要真正的修复,请查看评论。

4

3 回答 3

4

config.hinclude时debug.hdebug.h将尝试包含,config.h但由于CONFIG已经定义了保护宏,因此config.h将跳过追溯的“包含”,并且解析将在下一行继续:

void somePrintingFunction(Config* conf);

没有Config定义类型。

正如StoryTellerConfig_t所指出的,您可以通过前向声明结构来打破相互依赖:

struct Config_t;
void somePrintingFunction(struct Config_t* conf);

从 C11 开始,您也可以这样做,typedef因为 C11 可以处理重复的 typedef,只要它们引用相同的类型。

typedef struct Config_t Config;
void somePrintingFunction(Config* conf);

(聚合(结构或联合)的前向声明不允许您声明这些类型的对象(除非已经提供了完整的定义),但是由于 C 保证所有指向结构或联合的指针必须看起来相同,所以它们就足够了允许您开始使用指向这些类型的指针。)

于 2018-11-22T13:44:25.347 回答
3

问题在于循环包含。在声明结构之前,您实际上已经包含了您的函数。假设您包含config.h(假设您删除了错误的包含a.h,预处理器会这样做:

#include "debug.h"

typedef struct Config_t {
    /* some stuff */
} Config;

并定义符号CONFIG以使该文件不会被包含两次。然后它评估剩余的包括:

#include "config.h"

void somePrintingFunction(Config* conf);


typedef struct Config_t {
    /* some stuff */
} Config;

并定义符号DEBUG。由于定义了符号,因此它CONFIG不会包含config.h第二次,因此它已完成。现在注意函数的声明是如何在结构声明之前的。要解决这个问题,请使用这样的前向声明

#include "config.h"

struct Config_t;
void somePrintingFunction(struct Config_t* conf);

Config所以编译器在你使用它之前就知道它是什么。请记住在文件中定义所有使用预先声明的结构或类的函数,c因为预先声明的对象尚未定义,但将在c文件中。

编辑:我应该提到循环包含不是一件好事,您通常可以找到另一种不太危险的解决方案。

于 2018-11-22T13:40:00.660 回答
2

debug.h不需要其他标题。您可以使用Config_t单独的前向声明来定义该函数

struct Config_t;
void somePrintingFunction(struct Config_t* conf);
于 2018-11-22T13:32:01.987 回答