预处理器条件分布在`#include`文件中

时间:2016-10-24 06:08:55

标签: c c-preprocessor language-lawyer

这合法吗?

foo.h

    #if 1
    #include "bar.h"

bar.h

    #endif

foo.c

    #include "foo.h"

clang-700.1.81以一种有趣的方式抱怨:

    In file included from foo.c:1:
    In file included from ./foo.h:2:
    ./bar.h:1:2: error: #endif without #if
    #endif

(这意味着 #include "bar.h"

    # 3 "./foo.h" 2
    In file included from foo.c:1:
    ./foo.h:1:2: error: unterminated conditional directive
    #ifndef FOO

(这意味着它没有 #include "bar.h")。

我有一种不安的感觉,预处理器关心的不仅仅是标准要求它。如果我错了,请纠正我,或者如果我是对的,请纠正。

3 个答案:

答案 0 :(得分:4)

这不合法。构成条件部分的所有条件指令必须在同一个文件中,尽管条件组可能包含#include指令或嵌套的条件部分。

这个约束由预处理文件的语法(第6.10节)明确表示。

      preprocessing-file:
               group opt
      group:
               group-part
               group group-part
      group-part:
               if-section
               control-line
               text-line
               # non-directive
      if-section:
               if-group elif-groups opt else-group opt endif-line

约束也隐含在§5.1.1.2第4段中,它描述了#include指令作为阶段1到4的递归执行的功能,而不是简单的文本包含:

  

#include预处理指令导致命名的头文件或源文件以递归方式从阶段1到阶段4进行处理。

答案 1 :(得分:2)

有趣的问题。我认为这可以通过C11标准在两个地方得到解答。

首先我们看一下§6.10中的语法,很明显#if#endif必须在同一个preprocessing-file中。如果名称本身不够,我们可以查看§5.1.1.1的定义:

  

5.1.1.1程序结构

     

1 C程序不需要同时翻译。保留了该程序的文本   在本国际标准中称为源文件(或预处理文件)的单元中。一个   源文件以及通过预处理包含的所有头文件和源文件   指令#include称为预处理转换单元

答案 2 :(得分:1)

ISO / IEC 9899对于翻译阶段3有这句话:

  

[cut]源文件不得以部分预处理令牌或部分注释结束。 [切割]

对我而言,这意味着包含componentWillUpdate的文件必须具有匹配的#if