是否将一个无符号整数右移其总位数UB



我想检查一些大的计算内存需求(存储在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 unsignedn"; 
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。

在gcc中可以正常工作。

但是MSVC 13:

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

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

根据c++标准(5.8 Shift操作符)

  1. 如果右操作数为负,或大于或等于升格数的长度,则未定义左操作数

C标准(6.5.7位移位操作符)

3对每个操作数进行整数提升。的结果的类型是提升后的左操作数的类型。如果值右操作数的值为负,或者大于等于

最新更新