是将无符号整数右移它的总位数UB吗?

时间:2015-05-31 14:44:21

标签: c++ bit-shift

我想检查一些大的计算内存需求(存储在unsigned long long中)是否与用于编译代码的内存模型大致兼容。

我认为,只有当内存需要适合虚拟地址空间时(无论实际操作系统限制如何),将需求右移需要指针中的位数才会产生0。

不幸的是,在一些编译器上将64位数字移位64位时,我发现了一些意想不到的结果。

小演示:

const int ubits =  sizeof (unsigned)*8;  // number of bits, assuming 8 per byte
const int ullbits =  sizeof (unsigned long long)*8; 
cout << ubits << " bits for an unsigned\n"; 
cout << ullbits << " bits for a unsigned long long \n";

unsigned  utest=numeric_limits<unsigned>::max();  // some big numbers
unsigned long long ulltest=numeric_limits<unsigned long long>::max();

cout << "unsigned "<<utest << " rshift by " << ubits << " = "
    << (utest>>ubits)<<endl; 
cout << "unsigned long long "<<ulltest << " rshift by " << ullbits << " = "
    << (ulltest>>ullbits)<<endl; 

我预计两个显示的rshit结果都是0.

works as expected with gcc

但是对于MSVC 13:

  • 在32位调试中:无符号上的32位rshift具有NO EFFECT(显示原始数字),但无符号long long的64位移位为0,如预期的那样。
  • 在64位调试中:rshift在两种情况下都没有效果。
  • 在32位和64位释放:两种情况下rshif都是0。

我想知道这是否是编译器错误,或者这是否是未定义的行为。

1 个答案:

答案 0 :(得分:5)

根据C ++标准(5.8移位运算符)

  
      
  1. ... 行为未定义如果右操作数为负数,或者大于或等于提升位的长度   左操作数
  2.   

C标准(6.5.7按位移位运算符)

中写的相同
  

3对每个操作数执行整数提升。该   结果的类型是提升的左操作数的类型。如果值   右操作数为负数或大于或等于   提升左操作数的宽度,行为未定义