【发布时间】:2009-10-20 22:36:10
【问题描述】:
根据 C/C++ 标准(see this link),C 和 C++ 中的 >> 运算符不一定是有符号数的算术移位。当位右移时,是否移入 0(逻辑)或符号位(算术)取决于编译器实现。
对于为有符号整数实现逻辑右移的编译器,此代码是否会在编译时执行断言(失败)?
#define COMPILE_TIME_ASSERT(EXP) \
typedef int CompileTimeAssertType##__LINE__[(EXP) ? 1 : -1]
#define RIGHT_SHIFT_IS_ARITHMETIC \
( (((signed int)-1)>>1) == ((signed int)-1) )
// SHR must be arithmetic to use this code
COMPILE_TIME_ASSERT( RIGHT_SHIFT_IS_ARITHMETIC );
【问题讨论】:
-
对于那些拥有使用逻辑移位的机器的人来说,你的失败编译会做什么?为什么您的软件不能在这样的机器/编译器上使用?不管有符号数的右移是算术还是逻辑,编写代码不是更好吗?
-
我正在通过位旋转使用无分支选择 (BFS)。它需要算术移位才能工作。我把 COMPILE_TIME_ASSERT( RIGHT_SHIFT_IS_ARITHMETIC );在 BFS 标头中。代码需要使用 RIGHT_SHIFT_IS_ARITHMETIC 定义来选择传统或无分支路径。由于分支预测错误,PS3/XBOX360 CPU 使用无分支代码可能会大大加快速度。
-
顺便说一句,编译时失败的编译断言明确指出原因比仅仅让代码神秘地失败要好......基本上它会说这些例程不受此支持编译器(或 CPU)。
-
Adisak:一定要描述一下你从那个掩码添加技巧中得到的改进——在 int 单元上,我发现它有时只是对普通的旧 cmp/bge 的改进,具体取决于如何好吧,编译器设法在它周围交错了东西。这不是
fsel的巨大胜利。 -
替代建议:如果您在编译时找不到执行此测试的好方法,那么在 main() 顶部进行快速运行时测试并崩溃并没有错如果运行时测试没有给出您想要的结果,则提供信息丰富的诊断/建议。它不如编译时错误好,但由于在测试中不能错过它,它避免了在启用不正确代码的情况下意外发布的可能性。