#line和字符串文字串联

时间:2014-11-28 01:03:25

标签: c gcc c-preprocessor c99 string-concatenation

鉴于这段 C 代码:

char s[] =

"start"

#ifdef BLAH
"mid"
#endif

"end";

预处理器的输出应该是多少?换句话说,实际编译器应该接收并能够处理什么?为了缩小可能性,让我们坚持使用C99。

我看到一些预处理器输出了这个:

#line 1 "tst00.c"
char s[] =

"start"
#line 9
"end";

或者这个:

# 1 "tst00.c"
char s[] =

"start"




# 7 "tst00.c"


"end";

gcc -E输出:

# 1 "tst00.c"
# 1 "<command-line>"
# 1 "tst00.c"
char s[] =

"start"





"end";

即使使用 -fpreprocessed 选项,gcc也可以很好地编译所有上述预处理代码,这意味着不需要进行进一步的预处理,因为所有这些都已经完成。

混淆源于1999年 C 标准的措辞:

5.1.1.2 Translation phases
1 The precedence among the syntax rules of translation is specified by the following
  phases.
...
4. Preprocessing directives are executed, macro invocations are expanded, and
_Pragma unary operator expressions are executed. ... All preprocessing directives are
then deleted.
...
6. Adjacent string literal tokens are concatenated.
7. White-space characters separating tokens are no longer significant. Each
preprocessing token is converted into a token. The resulting tokens are syntactically
and semantically analyzed and translated as a translation unit.

换句话说,#line指令出现在相邻字符串文字之间是否合法?如果是,则意味着实际编译器必须执行另一轮字符串文字串联,但标准中未提及。

或者我们只是处理非标准的编译器实现,包括gcc?

1 个答案:

答案 0 :(得分:1)

为了人类读者和任何可能尝试使用文本形式的工具,我们会添加您从GCC -E(或兼容工具)获得的#line# 1行。预处理器的输出。它们只是为了方便。

通常,是的,指令可能出现在连接的字符串文字标记之间。 #line与您示例中的#ifdef没有区别。

  

或者我们只是处理非标准的编译器实现,包括gcc?

-E-fpreprocessed模式未标准化。标准预处理器始终将其输出提供给编译器,而不是文本文件。此外:

预处理器的输出没有标准的文本表示。

插入#line指令的原因是,在再次预处理之前,您可能插入到已经预处理的文件中的任何__LINE____FILE__宏都将正确扩展。也许,在编译这样的文件时,编译器可能会在报告错误时注意并使用这些值。 “预处理文本文件”的使用是非标准的,通常不鼓励。