是否有一种标准方法来保证某些(常量)表达式将在编译(翻译)时进行评估?

Is there a standard way to guarantee that a certain (constant) expressions will be evaluated at compile (translation) time?

我很惊讶 C 不保证某些(常量)表达式在编译(翻译)时被求值。

C11(6.6 常量表达式)(重点添加):

A constant expression can be evaluated during translation rather than runtime, ...

因此,两个问题:

  1. 是否有标准的方法来保证某个(常量)表达式在编译(翻译)时被计算?
  2. 附加问题:为什么C不保证呢?保证它的(技术)障碍是什么?

可能只是对英语的轻微歧义使用:术语“can”在这里(恕我直言)用于表达表达式是编译时的逻辑可能性可评估的,而不是可选的实施指令。

如果我们从标准中引用您引用的段落的完整文本(强调的粗体斜体是我的),那么我相信可以保证评估有效 发生在编译时:

6.6 Constant expressions

Description
2   A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be.

C 标准通常无助于分别描述编译时和 运行 时可能发生的情况。整个语言基于 C17 5.1.2.3

中“抽象机”的(相当无用的)概念

The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant.
...
Evaluation of an expression in general includes both value computations and initiation of side effects...
In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced...

上面包含了evaluation的正式定义,这也没什么用。基本上,只要尊重副作用和“可观察到的行为”,实现就可以自由地以优化的方式做任何事情。没有要求说明编译器必须执行某些优化。构建一个完全没有优化的编译器是可能的,它仍然可以是一个符合标准的实现。

至于 6.6 和常量表达式,其目的肯定是说明什么是有效编译时常量的规则。如果整数常量表达式没有在编译时求值,那么生成可执行文件就变得非常不切实际,以至于整个语言都会崩溃。间接地,除非在编译时评估常量表达式,否则有许多要求无法满足。

例如,如果在编译时不知道静态存储持续时间对象的数组大小,那么您将如何生成用于初始化它们的启动代码?它必须在调用 main() 之前发生——这实际上由 5.1.2:

保证

All objects with static storage duration shall be initialized (set to their initial values) before program startup.

并且如果 main 包含 static int arr [5] = {1,2,3,4,5}; 那么这个对象必须在我们到达声明时已经初始化。因此,如果我的示例中的整数常量 5(整数常量表达式)实际上是在编译时计算的,那么我们只能满足 5.1.2。