表达式中多位移位运算符出现异常行为的原因咨询
问题
编写程序时发现位移位异常,编写测试用例排查问题,测试代码如下:
#include <iostream> #include <Windows.h> #include <bitset> using namespace std; int main(){ BYTE byte = 0b10010000; //This is 2^7 + 2^4 = 144 cout << "This is the binary number 10010000: " << endl << "Numerical value: " << (unsigned short int) byte << endl << "Binary string: " << bitset<8>(byte) << endl; byte = byte << 1; cout << "Shifted left by 1 with << 1:" << endl << "Numerical value: " << (unsigned short int) byte << endl << "Binary string: " << bitset<8>(byte) << endl; byte = byte >> 5; cout << "Shifted right by 5 with >> 5: " << endl << "Numerical value: " << (unsigned short int) byte << endl << "Binary string: " << bitset<8>(byte) << endl; byte = 0b10010000; byte = (byte << 1) >> 5; //Expect to store 00000001 inside byte cout << "But what happens if I do it all in one line? " << endl << "Numerical value: " << (unsigned short int) byte << endl << "Binary string: " << bitset<8>(byte) << endl; return 0; }
运行结果差异:
- 分步执行左移1位再右移5位,结果为1(二进制
00000001),符合预期; - 合并为一行表达式
byte = (byte << 1) >> 5;执行时,结果为9(二进制00001001),与预期不符。
BYTE是Windows定义的数据类型,请求解释该异常原因。
原因解释
这个差异的核心是C++的整数提升规则在起作用:
BYTE本质是unsigned char(Windows头文件中定义为typedef unsigned char BYTE;),属于窄整数类型。- 分步执行逻辑:
- 第一步
byte = byte << 1;:byte作为unsigned char参与左移,8位的0b10010000左移1位后,最高位的1被丢弃,得到0b00100000(数值32),赋值回byte后仍是8位数据。 - 第二步
byte = byte >> 5;:32(0b00100000)右移5位,得到0b00000001(数值1),符合预期。
- 第一步
- 合并表达式执行逻辑:
- 在表达式
(byte << 1) >> 5中,byte会先被整数提升为int类型(因为unsigned char的取值范围完全包含在int内,C++标准会自动做提升)。 - 左移操作在32位
int上进行:0b10010000(144)提升为int后是0x00000090,左移1位得到0x00000120(二进制0000000100100000),此时最高位的1不会被丢弃,因为int有足够的位数容纳。 - 接着对这个32位值右移5位,得到
0x00000009(二进制00001001),最后赋值回byte时截断为8位,结果就是9。
- 在表达式
简言之:分步执行时每一步都把结果截断回8位的BYTE,合并表达式时中间结果保留为32位int,导致右移时保留了原本会被截断的高位数据。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

