4

K&R c 第 2 版(第 2.3 节)提到

常量表达式是只包含常量的表达式。这样的表达式可以在编译期间而不是运行时进行评估,因此可以在任何可能出现常量的地方使用

但是,我对此有几个疑问:

  1. 这个表达式会被视为常量表达式吗?

    const int x=5;
    const int y=6;
    int z=x+y;
    

    即使用const关键字是否被认为是常量表达式?

  2. 是否有任何技术可以检查表达式是在编译期间还是在运行时评估的?

  3. 是否存在编译时评估产生与运行时评估不同的结果的情况?

  4. 我什至应该关心它吗?(也许我用它来优化我的程序)

4

4 回答 4

2
  1. 也许。编译器可以添加更多形式的常量表达式,因此如果它可以向自己证明变量引用足够常量,它就可以在编译时计算表达式。
  2. 您可以(当然)反汇编代码并查看编译器做了什么。
  3. 如果编译器符合标准,则不会。该标准说“评估常量表达式的语义规则与非常量表达式的语义规则相同”(C11 草案中的第 6.6 11 节)。
  4. 不是很多,不。:) 但是const无论如何都要使用这样的代码!
于 2015-07-08T14:15:23.693 回答
1

使用 const 关键字是否被视为常量表达式?

>>不,它不是一个常数。变量 usingconst称为constqualified,但不是编译时常量。

是否有任何技术可以检查表达式是在编译期间还是在运行时评估的?

>>Unwind先生的回答中所述)反汇编代码。

是否存在编译时评估产生与运行时评估不同的结果的情况?

>>不,它不会。参考章节§6.6 11C11标准。

FWIW,如果与sizeof运算符一起使用(编译时,虽然不是常量表达式),NULL 指针取消引用就可以了。编译时 NULL 指针取消引用调用 未定义的行为

我什至应该关心它吗?(也许我用它来优化我的程序)

>>基于意见,所以不会回答。

于 2015-07-08T14:08:18.873 回答
0
  1. x 和 y 是 const,z 不是。编译器可能会替换 x 和 y ,但不会替换 z。但可能编译器也会计算 5 + 6 并直接分配给 z 。

  2. 不确定您是否可以检查生成的汇编代码,但我不知道如何做到这一点。

  3. 不是。编译时意味着表达式已经在运行时计算。

  4. 我在乎 :) 但它只适用于您需要快速执行的情况。

于 2015-07-08T14:19:13.853 回答
0
  1. 在 C 中,const 限定符只是程序员向编译器提供的保证,即他不会更改对象。否则,它没有 C++ 中的特殊含义。具有文件或全局范围的此类对象的初始化程序必须是常量表达式

  2. 作为扩展,gcc 有一个内置函数 ( int __builtin_constant_p (exp)) 来确定一个值是否为常数。

  3. 不,它不应该 - 除非您利用实现定义未定义的行为并且编译器和目标的行为不同。[1]

  4. 由于常量表达式是在编译时评估的,因此它们可以确保处理时间以及代码空间和可能的数据空间。此外,在某些地方(例如全局初始化器),只允许使用常量表达式。见标准。


[1]:一个例子是右移一个有符号负整数常数,例如-1 >> 24。由于这是实现定义的,编译器可能会产生与使用具有相同值的变量运行的程序不同的结果:

int i = -1;
(-1 >> 24) == (i >> 24)
^             ^--- run-time evaluated by target
+--- compile-time evaluated by compiler

比较可能会失败。

于 2015-07-08T14:35:44.520 回答