需要澄清常量表达式

时间:2015-07-08 14:06:31

标签: c constant-expression

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

  

常量表达式是仅涉及常量的表达式。这些表达式可以在编译期间而不是在运行时进行评估,因此可以在任何可以发生常量的地方使用

然而,我对它有几个疑问:

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

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

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

  2. 有没有什么技术可以检查表达式是在编译期间还是在运行期间进行评估的?

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

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

4 个答案:

答案 0 :(得分:2)

  1. 也许。编译器可以添加更多形式的常量表达式,因此如果它可以向自己证明变量引用足够常量,它可以在编译时计算表达式。
  2. 您当然可以反汇编代码并查看编译器的功能。
  3. 如果编译器符合标准,则不会。标准说“评估常量表达式的语义规则与非常量表达式相同”(C11草案中的§6.611)。
  4. 不是很多,没有。 :)但是,无论如何都要使用const代码!

答案 1 :(得分:1)

  使用const关键字的

是否被认为是常量表达式?

>> 不,它不是常量。使用const的变量称为 const限定,但不是编译时常量。

  

有没有什么技术可以检查表达式是在编译期间还是在运行期间进行评估的?

>> Unwind先生的回答中提及)反汇编代码。

  

编译时评估是否会产生与运行时评估不同的结果?

>> 不,它不会。请参阅第§6.6 11章,C11标准。

FWIW,如果使用sizeof运算符(编译时,虽然不是常量表达式),NULL指针取消引用将是正常的。编译时NULL指针取消引用调用undefined behaviour

  

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

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

答案 2 :(得分:0)

  1. x和y是const,z不是。 compiller可能会替换x和y,但不会替代z。但是compiller也可以计算5 + 6,并直接分配给z。

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

  3. 不。编译时表示表达式已在运行时计算。

  4. 我关心:)但只有当你需要快速执行时它才适用。

答案 3 :(得分:0)

  1. 在C中,const 限定符只是程序员向编译器提供的保证,他不会更改对象。否则它没有像C ++那样具有特殊含义。具有文件范围或全局范围的此类对象的初始值设定项必须为constant expression

  2. 作为扩展程序,gcc具有builtin函数(int __builtin_constant_p (exp))来确定值是否为常量。

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

  4. 由于常量表达式是在编译时计算的,因此它们可以安全地处理时间并且通常是代码空间和可能的数据空间。此外,在某些地方(例如全局初始值设定项),只允许常量表达式。见标准。

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

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

    比较可能会失败。