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

Chr*_*phe 0 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; 
Run Code Online (Sandbox Code Playgroud)

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

与gcc一样正常.

但是使用MSVC 13:

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

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

Vla*_*cow 5

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

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

同样写在C标准中(6.5.7按位移位运算符)

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