预处理在此代码段中如何工作?
How does preprocessing work in this snippet?
#include<stdio.h>
#define A -B
#define B -C
#define C 5
int main() {
printf("The value of A is %dn", A);
return 0;
}
我看到了上面的代码。我认为经过预处理后,它会转换为
// code from stdio.h
int main() {
printf("The value of A is %dn", --5);
return 0;
}
这应该会导致编译错误。但是,代码可以正常编译并生成输出 5
.
在这种情况下如何对代码进行预处理,以免导致编译器错误?
PS:我在 Linux x86-64 上使用 gcc 版本 8.2.0。
预处理器定义为对 令牌 流进行操作,而不是文本。您必须通读 C 标准的所有部分 5.1.1, 6.4, and 6.10 才能完全理解其工作原理,但关键位在 5.1.1.1 "Phases of translation" 中:在阶段 3 中,源文件是 "decomposed into preprocessing tokens";第 4、5 和 6 阶段对这些代币进行操作;在第 7 阶段 "each preprocessing token is converted into a token"。那个不定冠词很关键:每个预处理标记都变成 一个 个标记。
这意味着,如果你从这个源文件开始
#define A -B
#define B -C
#define C 5
A
然后,在翻译阶段 4(宏扩展等)之后,您得到的是三个预处理标记的序列,
<punctuator: -> <punctuator: -> <pp-number: 5>
并且在翻译阶段 7 开始时变为
TK_MINUS TK_MINUS TK_INTEGER:5
然后被解析为表达式 -(-(5))
而不是 --(5)
。该标准在这方面没有提供任何自由度:将您的示例解析为 --(5)
的 C 编译器有缺陷。
当您要求编译器将预处理后的源代码转储为文本时,标准并未指定该文本的格式;通常,您得到的内容会根据需要插入空格,以便人们可以像翻译阶段 7 那样理解它。
#include<stdio.h>
#define A -B
#define B -C
#define C 5
int main() {
printf("The value of A is %dn", A);
return 0;
}
我看到了上面的代码。我认为经过预处理后,它会转换为
// code from stdio.h
int main() {
printf("The value of A is %dn", --5);
return 0;
}
这应该会导致编译错误。但是,代码可以正常编译并生成输出 5
.
在这种情况下如何对代码进行预处理,以免导致编译器错误?
PS:我在 Linux x86-64 上使用 gcc 版本 8.2.0。
预处理器定义为对 令牌 流进行操作,而不是文本。您必须通读 C 标准的所有部分 5.1.1, 6.4, and 6.10 才能完全理解其工作原理,但关键位在 5.1.1.1 "Phases of translation" 中:在阶段 3 中,源文件是 "decomposed into preprocessing tokens";第 4、5 和 6 阶段对这些代币进行操作;在第 7 阶段 "each preprocessing token is converted into a token"。那个不定冠词很关键:每个预处理标记都变成 一个 个标记。
这意味着,如果你从这个源文件开始
#define A -B
#define B -C
#define C 5
A
然后,在翻译阶段 4(宏扩展等)之后,您得到的是三个预处理标记的序列,
<punctuator: -> <punctuator: -> <pp-number: 5>
并且在翻译阶段 7 开始时变为
TK_MINUS TK_MINUS TK_INTEGER:5
然后被解析为表达式 -(-(5))
而不是 --(5)
。该标准在这方面没有提供任何自由度:将您的示例解析为 --(5)
的 C 编译器有缺陷。
当您要求编译器将预处理后的源代码转储为文本时,标准并未指定该文本的格式;通常,您得到的内容会根据需要插入空格,以便人们可以像翻译阶段 7 那样理解它。