按位运算是否解析为常量值

时间:2014-11-30 12:08:26

标签: c++ variables bit-manipulation constants

我只是想知道是否有人知道按位AND和OR以及对常量进行操作的按位移位是否会被编译器预先计算为常数值。

例如int Foo = Bar / ( 1 << 12 )

我这样做而不是Bar >> 12的原因是,如果Bar是负值,它会下降到-1而不是零。

4 个答案:

答案 0 :(得分:4)

  

&#34;我只是想知道是否有人知道按位AND和OR以及对常量进行操作的按位移位是否会被编译器预先计算为常数值。&#34;

是的

( 1 << 12 )

部分将在编译时进行评估。

它实际上和写作一样

int Foo = Bar / 4096;

答案 1 :(得分:1)

即使是最蹩脚的编译器也会像这样进行简单的常量折叠。真的,你可能会在大学的编译器课程中实现它,这就是它的水平。

编译器偶尔会对我们人类做一些看似愚蠢的事情,通常是无法检测到的“全局”事物。但是编译器在这种类型的东西上很棒,它只需要一些本地可用的信息,它可以查看代码内部表示的一小部分,并将其与一些已知模式相匹配。两个众所周知的例子是恒定折叠和强度降低。

所以你真的可以期待更多,这种分裂应该消失。有一个众所周知的(在编译器构建圆圈中)通过一个常数将除法转换为(粗略地,忽略细节)乘法和移位,并且有一个更简单的分配方法用于已知的2的幂(这个情况下!)

GCC on -O2转向了这个:

int foo(int x)
{
    return x / (1 << 12);
}

进入这个:

lea eax, [rdi+4095]
test    edi, edi
cmovns  eax, edi
sar eax, 12
ret

没有左移,没有分裂。它增加了4095个非正数,使它们以正确的方式进行。

答案 2 :(得分:0)

在C ++ 11中,您可以使用&#39; constexpr&#39;强制编译器在编译时以常量表达式进行计算

答案 3 :(得分:0)

通常,如果您想知道编译器是否可以在编译时计算常量整数值(不使用constexpr),请尝试使用计算值作为C数组的大小。

int arr[Bar / ( 1 << 12 )];

如果它编译,你知道它成功了,因为C数组大小在编译时必须是常量。

相关问题