ton*_*ark 5 c macros preprocessor
#include<stdio.h>
#define A -B
#define B -C
#define C 5
int main() {
printf("The value of A is %dn", A);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我遇到了上面的代码.我认为在预处理之后,它会被转换为
// code from stdio.h
int main() {
printf("The value of A is %dn", --5);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这应该导致编译错误.但是,代码编译良好并产生输出5.
在这种情况下如何对代码进行预处理,以免导致编译器错误?
PS:我在Linux x86-64上使用gcc版本8.2.0.
预处理器被定义为在令牌流上运行,而不是文本.你必须通过所有部分的阅读5.1.1,6.4和6.10 C标准的充分理解它是如何工作的,但关键位是5.1.1.1"翻译的阶段":在第3阶段,源文件"分解为预处理令牌"; 第4,5和6阶段对这些令牌进行操作; 并且在阶段7"每个预处理令牌被转换为令牌".这篇不定冠词至关重要:每个预处理令牌都只是一个令牌.
这意味着,如果你从这个源文件开始
#define A -B
#define B -C
#define C 5
A
Run Code Online (Sandbox Code Playgroud)
然后,在翻译阶段4(宏扩展等)之后,你所拥有的是一系列三个预处理令牌,
<punctuator: -> <punctuator: -> <pp-number: 5>
Run Code Online (Sandbox Code Playgroud)
并且在翻译阶段7的开始变为
TK_MINUS TK_MINUS TK_INTEGER:5
Run Code Online (Sandbox Code Playgroud)
然后将其解析为表达式-(-(5))而不是as --(5).该标准没有提供任何自由度:一个C编译器解析您的示例--(5)是有缺陷的.
当您要求编译器将预处理的源转储为文本时,标准不会指定该文本的形式; 通常情况下,您获得的内容会根据需要插入空格,以便人类能够像翻译阶段7一样理解它.