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

时间:2012-01-03 14:10:06

标签: c++ bit-manipulation

我从左移的结果得到了我无法找到解释的结果。

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,但我得int(?),其值为1 1111 1110

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

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

F0        F5
1111 0000 1111 0101 

可能是

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

这与使用小于int的类型进行算术的事实有关吗?

3 个答案:

答案 0 :(得分:9)

引用2011年标准草案:

  

5.8移位运算符[expr.shift]

     

...

     

操作数应为整数或无范围的枚举类型,并执行整体促销。   结果的类型是提升的左操作数的类型。

  

4.5积分促销[conv.prom]

     

除bool,char16_t,char32_t或wchar_t之外的整数类型的整数转换的整数转换   如果int可以表示all,则rank(4.13)小于int的rank可以转换为int类型的prvalue   源类型的值;否则,源prvalue可以转换为unsigned类型的prvalue   INT

     

...

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

您可以通过以下方式之一获得所需的结果:

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

答案 1 :(得分:2)

将其强制转换为无符号字符:

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

或者,使用按位-AND:

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

答案 2 :(得分:2)

您可以屏蔽您感兴趣的位:

(value << shift) & 0xff

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