【问题标题】:Why result of unsigned char << unsigned char is not unsigned char为什么 unsigned char << unsigned char 的结果不是 unsigned char
【发布时间】:2012-01-03 14:10:05
【问题描述】:

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

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

如何将 unsigned char 的位左移,使位被截断,结果为 1111 1110?

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

F0        F5
1111 0000 1111 0101 

可能

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

这是否与小于 int 的类型不进行算术运算有关?

【问题讨论】:

  • 11111111 value = value << shift; 然后cout &lt;&lt; value;

标签: c++ bit-manipulation


【解决方案1】:

引用 2011 年标准的一些草案:

5.8 移位运算符 [expr.shift]

...

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

4.5 整体促销 [conv.prom]

除 bool、char16_t、char32_t 或 wchar_t 之外的整数类型的纯右值,其整数转换 rank (4.13) 小于 int 的 rank 可以转换为 int 类型的纯右值,如果 int 可以表示所有 源类型的值;否则,源纯右值可以转换为无符号类型的纯右值 诠释

...

所以,value 被提升为intvalue &lt;&lt; shift 的类型就是被提升的左操作数的类型,即int

您可以通过以下方式之一达到您想要的结果:

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

【讨论】:

    【解决方案2】:

    只需将其转换回无符号字符即可:

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

    或者,使用按位与:

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

    【讨论】:

      【解决方案3】:

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

      (value << shift) & 0xff
      

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

      【讨论】:

        猜你喜欢
        • 2011-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-27
        • 1970-01-01
        • 2016-07-07
        相关资源
        最近更新 更多