C 预处理器指令是不是每次都重新计算?
Posted
技术标签:
【中文标题】C 预处理器指令是不是每次都重新计算?【英文标题】:Does C preprocessor directives recompute each time?C 预处理器指令是否每次都重新计算? 【发布时间】:2020-08-29 15:40:05 【问题描述】:我有这行代码:
#define ALPHABET_SIZE 'z' - 'a' + 1
当我将鼠标悬停在代码中任何位置的 ALPHABET_SIZE 上时,它告诉我它扩展为 'z' - 'a' + 1
。
所以我想知道每次我在代码中使用 ALPHABET_SIZE 时是否必须重新计算这个表达式?如果是这样,我该如何防止重新计算?
【问题讨论】:
可行,只是好奇。 我希望编译器会在编译时计算它,并且您的代码中只有 26 秒,除非您故意在关闭优化的情况下进行编译。 哦,你是说优化会自动处理它? 但要小心'z'-'a' +1
。使用('z'-'a'+1)
,否则4*ALPHABET_SIZE
之类的东西会给你带来意想不到的结果
【参考方案1】:
#define ALPHABET_SIZE 'z' - 'a' + 1
预处理器替换每个ALPHABET_SIZE
有
'z' - 'a' + 1
然后编译器很可能会执行Constant folding 优化,将计算替换为 26。
演示https://godbolt.org/z/Mo46db,表达式用gcc 10.2替换为26
【讨论】:
【参考方案2】:C 标准仅指定程序的可观察行为,而不是它们在后台的工作方式。
是否每次都重新计算'z' - 'a' + 1
不会影响可观察行为,因此由实现决定。
通常,您可以期望合理的编译器在编译时计算结果,尤其是在启用优化时。
【讨论】:
【参考方案3】:考虑以下程序:
#define ALPHABET_SIZE 'z' - 'a' + 1
#include <stdio.h>
int main(void)
printf("%d\n", 2*ALPHABET_SIZE);
printf("%d\n", ALPHABET_SIZE*2);
在我的 C 实现中,这会打印“148”和“27”。这是因为,在第一个 printf
中,2*ALPHABET_SIZE
被替换为 2*'z' - 'a' + 1
,其计算结果为 (2*'z') - 'a' + 1
,并且在第二个 printf
中,ALPHABET_SIZE*2
被替换为 'z' - 'a' + 1*2
,即评估为'z' - 'a' + (1*2)
。由于它们产生了两个不同的结果,因此证明了使用 C 语义的预处理不会用计算一次的单个表达式结果替换宏;它必须产生其他东西(实际上是一系列预处理器标记),随后在上下文中重新解释。
【讨论】:
以上是关于C 预处理器指令是不是每次都重新计算?的主要内容,如果未能解决你的问题,请参考以下文章