【发布时间】:2014-10-20 20:24:27
【问题描述】:
在 C11、C++11 和 C++14 中执行以下操作是否合法?
static_assert(((-4) >> 1) == -2, "my code assumes sign-extending right shift");
或 C 等价物:
_Static_assert(((-4) >> 1) == -2, "my code assumes sign-extending right shift");
我不知道关于是否可以使用上述实现定义的操作的常量表达式规则。
我知道,无论机器类型如何,负数的相反的有符号左移是未定义的。
【问题讨论】:
-
考虑在你的代码中使用
/来完全避免这个问题。无论班次定义如何,(-4) / 2始终为-2。 -
@Matt:虽然,它有向零舍入,而移位硬件经常向下舍入。所以它很容易以非常慢的速度结束,也许四舍五入是我们想要的。
-
@MattMcNabb:我的代码滥用签名
>>的原因是我可以在高位构建掩码。例如,x >> 31等价于x < 0 ? -1 : 0。当然,编译器已经为您进行了优化,但有时它不看到它在做什么。此外,这是在我的代码中非常热门的部分完成的。 -
@Myria 尝试检查编译器在最大优化级别生成的程序集,看看这是否真的是一个问题。在我的带有
gcc -O3的系统上,它对两者都有sarl $31, %eax。最大便携性和最大速度通常是相互矛盾的目标。 -
对于它的价值,即使编译器不支持它,编写一个宏来执行算术,二进制补码右移也是微不足道的,任何好的优化编译器都会崩溃到只是对自然具有您想要的行为的目标进行正常转变。
标签: c++ c c++11 language-lawyer c11