为什么二进制等效计算不正确?

18 c++ binary

我编写了以下程序来输出一个整数的二进制等价物(我检查了我的系统上的int是4个字节)它是4个字节.但输出并不合适.代码是:

#include<iostream>
#include<iomanip>
using namespace std;

void printBinary(int k){
    for(int i = 0; i <= 31; i++){
        if(k & ((1 << 31) >> i))
            cout << "1";
        else 
            cout << "0";
    }
}

int main(){
    printBinary(12);
}
Run Code Online (Sandbox Code Playgroud)

我哪里弄错了?

Yu *_*Hao 29

问题在于1<<31.因为2 31不能用32位有符号整数表示(范围-2 31到2 31 - 1),所以结果是未定义的[1].

修复很简单:1U<<31.


[1]:自C++ 14以来,行为是实现定义的.

  • @MattMcNabb:我没有看到OP被标记为C++ 14 (4认同)
  • @MattMcNabb:你的短语听起来像是想表明余浩是不正确的.我的观点是,他不是因为OP没有说明具体版本. (4认同)
  • [自C++ 14起](http://stackoverflow.com/questions/26331035/why-was-1-31-changed-to-be-implementation-defined-in-c14)没有UB (3认同)

das*_*ght 8

这个表达式不正确:

if(k & ((1<<31)>>i))
Run Code Online (Sandbox Code Playgroud)

int是一种带符号的类型,因此当您移动131次时,它将成为系统上的符号位.之后,将结果右移i一次符号 - 扩展数字,这意味着顶部位保持为1s.最终得到一个如下所示的序列:

80000000 // 10000...00
C0000000 // 11000...00
E0000000 // 11100...00
F0000000 // 11110...00
F8000000
FC000000
...
FFFFFFF8
FFFFFFFC
FFFFFFFE // 11111..10
FFFFFFFF // 11111..11
Run Code Online (Sandbox Code Playgroud)

要解决此问题,请将表达式替换为1 & (k>>(31-i)).这样,您可以避免因移位到符号位置而导致的未定义行为*1.

* C++ 14更改了定义,因此1在32位中向左移动31次int不再是未定义的(谢谢,Matt McNabb,指出这一点).