[英]Include Guards in C
我有2個頭文件,必須包含另一個頭文件。
config.h:
#ifndef CONFIG
#define CONFIG
#include "debug.h"
typedef struct Config_t {
/* some stuff */
} Config;
#endif
調試
#ifndef DEBUG
#define DEBUG
#include "config.h"
void somePrintingFunction(Config* conf);
#endif
這是我得到的錯誤:
debug.h:錯誤:未知類型名稱“ Config”
config.c:警告:函數“ somePrintingFunction”的隱式聲明
debug.h:錯誤:未知類型名稱“ Config”
我猜它在頭聲明中循環了嗎?
編輯:
修復了合並兩個文件的問題,從而簡化了項目設計。 如果您要進行真正的修復,請在注釋中簽入。
當config.h
包含debug.h
, debug.h
將嘗試包含config.h
但是由於已經定義了CONFIG
保護宏,因此將跳過config.h
的追溯性“ include”,並且解析將繼續進行。下一行:
void somePrintingFunction(Config* conf);
沒有定義Config
類型。
正如StoryTeller所指出的,您可以通過向前聲明Config_t
結構來打破相互依賴性:
struct Config_t;
void somePrintingFunction(struct Config_t* conf);
從C11開始,您還可以執行typedef
因為C11可以處理重復的typedef,只要它們引用相同的類型即可。
typedef struct Config_t Config;
void somePrintingFunction(Config* conf);
(聚合(結構或聯合)的前向聲明不允許您聲明這些類型的對象(除非已提供完整的定義),但由於C保證所有指向結構或聯合的指針必須看起來相同,所以它們就足夠了讓您開始使用指向這些類型的指針。)
問題在於循環包含。 在聲明結構之前,實際上是在包含函數。 可以說您包含config.h
(假設您刪除了錯誤的包含ah
,預處理器會這樣做:
#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
文件中。
編輯:我應該提一下,循環包含並不是一件好事,您通常可以找到另一種解決方案,這種解決方案的風險較小。
debug.h
不需要其他標頭。 您可以單獨使用Config_t
的前向聲明來定義該函數
struct Config_t;
void somePrintingFunction(struct Config_t* conf);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.