为什么无符号字符 << 无符号字符的结果不是无符号字符。

7

我得到了左移的结果,但找不到解释。

unsigned char value = 0xff; // 1111 1111
unsigned char  = 0x01; // 0000 0001

std::cout << "SIZEOF value " << sizeof(value) << "\n"; // prints 1 as expected
std::cout << "SIZEOF shift " << sizeof(shift) << "\n"; // prints 1 as expected

std::cout << "result " << (value << shift) << "\n"; // prints 510 ???

std::cout << "SIZEOF result " <<  sizeof(value << shift) << "\n"; // prints 4 ???

我希望结果为1111 1110,但实际结果为值为1 1111 1110int数据类型。

如何将无符号字符的位左移,以便截断位并得到结果为1111 1110?

我的目标是读取一系列字节,并将它们解释为长度不同的整数(1-32位)。

F0        F5
1111 0000 1111 0101 

可能是

0F (first 4 bits)
0F (next 8 bits)
05 (last 4 bits)

这与算术不使用比int更小的类型有关吗?


11111111 << 1 实际上是 111111110,你正在打印表达式的结果,请尝试执行:value = value << shift; 然后 cout << value; - Yaniro
3个回答

9

引用2011标准的一些草案:

5.8 移位运算符 [expr.shift]

...

操作数应为整型或未作用域枚举类型,将执行整型提升。 结果的类型是被提升的左操作数的类型。

4.5 整型提升 [conv.prom]

整数类型(bool、char16_t、char32_t或wchar_t以外)的prvalue,其整数转换等级(4.13)小于int的等级, 如果int能表示源类型的所有值,则可以将其转换为int类型的prvalue;否则,源prvalue可以转换为unsigned int类型的prvalue。

...

因此,value被提升为intvalue << shift的类型是被提升的左操作数的类型,即int

有以下几种方法可以实现您想要的结果:

std::cout << "result " << ((unsigned char)(value << shift)) << "\n";
std::cout << "result " << ((value << shift)&0xff) << "\n";

2
您可以屏蔽您感兴趣的位:
(value << shift) & 0xff

你所看到的是整数提升的结果,这是语言的一部分。想象一下,你正在从两个8位整数组成一个16位整数 - 你不想手动提升到更高的宽度整数,以便将高位和低位放在正确的位置吗?


2

只需将其转换为无符号字符:

std::cout << "result " << static_cast<unsigned char>(value << shift) << "\n";

或者,使用按位与运算符:

std::cout << "result " << ((value << shift) & 0xFF) << "\n";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接