需要澄清常量表达式
Need clarification about constant expressions
K&R c 第 2 版(第 2.3 节)提到
A constant expression is an expression that involves only constants. Such expressions may be evaluated at during compilation rather than run-time, and accordingly may be used in any place that a constant can occur
然而,我对此有几个疑问:
这个表达式会被认为是常量表达式吗?
const int x=5;
const int y=6;
int z=x+y;
即使用 const
关键字是否被视为常量表达式?
是否有任何技术可以检查表达式是否在编译期间或 运行 期间被计算?
是否存在编译时求值与 运行 时求值不同的结果?
我应该关心它吗? (也许我用它来优化我的程序)
using const keyword is considered constant expression or not?
>> 不,它不是常数。使用const
的变量称为const
限定,但不是编译时常量。
Is there any technique by which we can check whether an expression was evaluated during compilation or during run-time?
>>(如Unwind先生的回答中所述)反汇编代码
Are there any cases where compile time evaluation produces different result than run-time evaluation?
>> 不会的。参考章节§6.6 11
、C11
标准。
FWIW,如果使用 sizeof
运算符(编译时,虽然不是常量表达式),NULL 指针取消引用就可以了。编译时 NULL 指针取消引用调用 undefined behaviour.
Should I even care about it? (maybe I use it to optimize my programs)
>>个人观点,所以不会回答。
- 也许吧。编译器可以添加更多形式的常量表达式,因此如果它可以向自己证明变量引用足够常量,它就可以在编译时计算表达式。
- 您(当然)可以反汇编代码并查看编译器做了什么。
- 如果编译器符合标准,则不会。该标准表示 "The semantic rules for the evaluation of a constant expression are the same as for nonconstant expressions"(C11 草案中的 §6.6 11)。
- 不多,不。 :) 但是无论如何都要对这样的代码使用
const
!
x 和 y 是常量,z 不是。编译器可能会替换 x 和 y,但不会替换 z。但可能编译器也会计算 5 + 6 并直接分配给 z。
不确定您是否可以检查生成的汇编代码,但我不知道如何做到这一点。
不是。编译时间意味着表达式已经在 运行 时间内计算出来。
我关心 :) 但它仅在您需要快速执行时才适用。
在C中,const
限定符只是程序员给编译器的保证,他不会改变对象。否则它不像在 C++ 中那样具有特殊含义。具有文件或全局范围的此类对象的 初始化程序 必须是 constant expression.
作为扩展,gcc 有一个 builtin 函数 (int __builtin_constant_p (exp)
) 来确定一个值是否为常量。
不,它不应该——除非你利用定义的实现或未定义的行为并且编译器和目标的行为不同. [1]
由于 常量表达式 在编译时求值,因此它们的处理时间很安全,并且经常编码 space 和可能的数据 space .此外,在某些地方(例如全局初始化器),只允许 常量表达式 。看标准。
[1]:一个例子是右移一个带符号的负整数常量,例如-1 >> 24
。由于这是实现定义的,编译器可能会从程序 运行 使用具有相同值的变量产生不同的结果:
int i = -1;
(-1 >> 24) == (i >> 24)
^ ^--- run-time evaluated by target
+--- compile-time evaluated by compiler
比较可能会失败。
K&R c 第 2 版(第 2.3 节)提到
A constant expression is an expression that involves only constants. Such expressions may be evaluated at during compilation rather than run-time, and accordingly may be used in any place that a constant can occur
然而,我对此有几个疑问:
这个表达式会被认为是常量表达式吗?
const int x=5; const int y=6; int z=x+y;
即使用
const
关键字是否被视为常量表达式?是否有任何技术可以检查表达式是否在编译期间或 运行 期间被计算?
是否存在编译时求值与 运行 时求值不同的结果?
我应该关心它吗? (也许我用它来优化我的程序)
using const keyword is considered constant expression or not?
>> 不,它不是常数。使用const
的变量称为const
限定,但不是编译时常量。
Is there any technique by which we can check whether an expression was evaluated during compilation or during run-time?
>>(如Unwind先生的回答中所述)反汇编代码
Are there any cases where compile time evaluation produces different result than run-time evaluation?
>> 不会的。参考章节§6.6 11
、C11
标准。
FWIW,如果使用 sizeof
运算符(编译时,虽然不是常量表达式),NULL 指针取消引用就可以了。编译时 NULL 指针取消引用调用 undefined behaviour.
Should I even care about it? (maybe I use it to optimize my programs)
>>个人观点,所以不会回答。
- 也许吧。编译器可以添加更多形式的常量表达式,因此如果它可以向自己证明变量引用足够常量,它就可以在编译时计算表达式。
- 您(当然)可以反汇编代码并查看编译器做了什么。
- 如果编译器符合标准,则不会。该标准表示 "The semantic rules for the evaluation of a constant expression are the same as for nonconstant expressions"(C11 草案中的 §6.6 11)。
- 不多,不。 :) 但是无论如何都要对这样的代码使用
const
!
x 和 y 是常量,z 不是。编译器可能会替换 x 和 y,但不会替换 z。但可能编译器也会计算 5 + 6 并直接分配给 z。
不确定您是否可以检查生成的汇编代码,但我不知道如何做到这一点。
不是。编译时间意味着表达式已经在 运行 时间内计算出来。
我关心 :) 但它仅在您需要快速执行时才适用。
在C中,
const
限定符只是程序员给编译器的保证,他不会改变对象。否则它不像在 C++ 中那样具有特殊含义。具有文件或全局范围的此类对象的 初始化程序 必须是 constant expression.作为扩展,gcc 有一个 builtin 函数 (
int __builtin_constant_p (exp)
) 来确定一个值是否为常量。不,它不应该——除非你利用定义的实现或未定义的行为并且编译器和目标的行为不同. [1]
由于 常量表达式 在编译时求值,因此它们的处理时间很安全,并且经常编码 space 和可能的数据 space .此外,在某些地方(例如全局初始化器),只允许 常量表达式 。看标准。
[1]:一个例子是右移一个带符号的负整数常量,例如-1 >> 24
。由于这是实现定义的,编译器可能会从程序 运行 使用具有相同值的变量产生不同的结果:
int i = -1;
(-1 >> 24) == (i >> 24)
^ ^--- run-time evaluated by target
+--- compile-time evaluated by compiler
比较可能会失败。