C++跳坑记:位移超出范围的处理

在C++编程中,数据类型的选择不仅影响内存占用和性能,还可以对某些操作的结果产生意想不到的影响。今天,我将分享一个关于C++在不同变量类型下位移操作结果的发现。

位移操作是C++中常见的对整数的高效操作之一。然而,我们可能会忽视一个细节:不同的编译器和数据类型可能会导致位移操作的结果不同。

示例代码

让我们看一个简单的计算512右移n位的代码,来展示这个问题:

#include <iostream>
using namespace std;

int main() {
    
    
    int L = 512;
    for (int i = 0; i < 64; i++) {
    
    
        cout << L << " >> " << i << " = " << (L >> i) << endl;
    }
    return 0;
}

在上述代码中,我们使用了一个整数 L,并尝试对其进行右移操作,观察结果:
512>>0 = 512
512>>1 = 256
512>>2 = 128
512>>3 = 64
512>>4 = 32
512>>5 = 16
512>>6 = 8
……
512>>30 = 0
512>>31 = 0
512>>32 = 512
512>>33 = 256
512>>34 = 128
……

发现

我天真地以为,只要右移的位数超出范围,结果为0。
但实际结果让我出乎意料:当 i 的值达到 32 时,512 >> 32 的结果变成了 512,然后往后,512 >> 33 等于 256,512 >> 34 等于 128,如此类推。
这与Python的计算表现完全不同。Python的运算结果是,只要超出范围,结果永远为零。
这意味着,当 i 大于等于 32 时,C / C++的右移操作不再产生预期的结果,而是保持原始值,这将严重影响后续的运算结果。

解决方案

为了解决这个问题,我们尝试将 L 的数据类型更改为 long,但很遗憾结果与使用 int 类型的情况一样,仍然无法得到正确的结果。
最后,我将 L 的类型更改为 long long,才得出了预期的结果。

#include <iostream>
using namespace std;

int main() {
    
    
	// 把L的类型由int改为long long
    long long L = 512;
    for (int i = 0; i < 64; i++) {
    
    
        cout << L << " >> " << i << " = " << (L >> i) << endl;
    }
    return 0;
}

运行结果截图

在这里插入图片描述

2023年10月5日更新

解决方法二:使用std::bitset
std::bitset<32> 是C++标准库中的一个固定大小的数据类型,它包含了32个二进制位,无法动态调整大小。这意味着无论如何,std::bitset<32> 都将保持32位的大小。

#include <iostream>
#include <bitset>
using namespace std;
int main() {
    
    
    int L1 = 512;
    bitset<32> L2(L1);  // 创建了一个包含32位的位集合,并将其初始化为512
    for(int i=0; i<=100; i++){
    
    
        cout << (L2>>i).to_ulong() << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Scott0902/article/details/133031034
今日推荐