【问题标题】:Include header file in C curiosity在 C 好奇心中包含头文件
【发布时间】:2012-04-12 01:59:43
【问题描述】:

我对包含文件及其管理方式有以下好奇心(GCC):

假设我有一个源文件 foo.c 和三个头文件 foo.hfoo_cfg.hfoo_int。 h

foo.c 中:

#include "foo.h"  
#include "foo_int.h" 

foo.h 中:

#include "foo_cfg.h" 

foo_cfg.h 中:

/* no inclusions */   
#define FOO BAR

foo_int.h 中:

/* no inclusions */ 
#define BAR 0U

我想知道为什么编译成功。 foo_cfg.h 文件不应该抱怨它不知道 BAR 符号吗?

此外,我还有另一个源文件 bar.c,它只包含 foo.h 文件并且仍然有效。

备注:这是来自我正在使用复杂的构建环境进行的一个项目,我不需要太多细节。除了指定header files的位置之外,会不会是构建环境对此有影响?

可能是这个问题真的很愚蠢,或者我忽略了一些东西,如果是这样,我深表歉意。

【问题讨论】:

    标签: c header


    【解决方案1】:

    不,没关系。

    你看,预处理器并不关心是否定义了 BAR。它只是在随后的源代码中将 string FOO 替换为 BAR,而实际上并不关心它是否在那时定义。

    接下来,在实际的 .c 文件(编译开始的地方)中包含两个头文件,因此编译器会看到两个替换:FOO -> BARBAR -> 0U。所以它成功地应用了它们。

    标头永远不会单独编译,它们始终作为.c 文件的一部分进行编译,#includes 该标头。 (预处理器只是假装标题的内容被粘贴到#include 所在的位置。)因此,对于预处理器,您的文件foo.c 看起来像这样:

    /* no inclusions */
    #define FOO BAR
    /* no inclusions */
    #define BAR 0U
    /* the rest of the file... */
    /* for example: */
    unsigned int i = FOO;
    

    预处理后的编译器只看到这个:

    /* no inclusions */
    /* no inclusions */
    /* the rest of the file... */
    /* for example: */
    unsigned int i = 0U;
    

    (不太确定,也许预处理器也会删除 cmets。)


    编辑:
    事实上,正如@pmg 所提到的,预处理器用空格替换了 cmets,因此提供给编译器的真正预处理文本只是

    _
    _
    _
    _
    unsigned int i = 0U;
    

    (这里_表示空格)

    【讨论】:

    • 您可以使用gcc -E file.c 在所有预处理完成后输出文件,但一旦您包含任何标准头文件,这可能会变得很长。
    • @Vlad:是的,预处理器在翻译阶段 3 中删除了 cmets。参见 the Standard 中的 5.1.1.2。
    • @pmg:谢谢!标准报价始终是信息的最终来源。我会更新我的答案。
    【解决方案2】:

    稍微扩展弗拉德的回答:

    预处理器宏在使用时展开,而不是在定义时展开。
    所以当你写 #define FOO BAR 时,它所做的只是记住 FOO=BAR。
    当你写#define BAR 0U时,它记得BAR=0U。

    现在,当在代码中看到FOO 时,它会被BAR 替换,而0U 会立即被替换为0U
    #define FOO#define BAR 在源中出现的顺序并不重要。重要的是,当第一次看到FOO 时,这两个定义都已经完成了。

    【讨论】:

    • 啊哈!这就是为什么 'bar.c' 不会抱怨没有包含 'foo_int.h',因为事实上它没有使用任何依赖于 'foo_int.h' 的定义。那么现在我开悟了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    相关资源
    最近更新 更多