C 预处理器指令是否每次都重新计算?

Does C preprocessor directives recompute each time?

我有这行代码:

#define ALPHABET_SIZE 'z' - 'a' + 1

当我将鼠标悬停在代码中的 ALPHABET_SIZE 上时,它告诉我它扩展到 'z' - 'a' + 1。 所以我想知道是否每次在我的代码中使用 ALPHABET_SIZE 时都必须重新计算这个表达式?如果是这样,我怎样才能防止重新计算?

C 标准仅指定程序的可观察行为,而不是它们在幕后的工作方式。

是否每次都重新计算 'z' - 'a' + 1 不会影响可观察到的行为,因此由实现决定。

一般来说,您可以期待明智的编译器在 compile-time 处计算结果,尤其是在启用优化时。

#define ALPHABET_SIZE 'z' - 'a' + 1

pre-processor替换每个ALPHABET_SIZE

'z' - 'a' + 1

然后编译器很可能会执行 Constant folding 优化,用 26 替换计算。


Demo https://godbolt.org/z/Mo46db,表达式被26替换为gcc 10.2

考虑以下程序:

#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 语义进行预处理不会用计算一次的单个表达式结果替换宏;它必须产生其他东西(实际上是一系列 预处理器标记 ),随后在上下文中重新解释。