简体   繁体   English

为什么unsigned char << unsigned char的结果不是unsigned char

[英]Why result of unsigned char << unsigned char is not unsigned char

I'm getting results from left shift to which I could not find an explanation. 我从左移获得结果,我无法找到解释。

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 ???

I was expecting result to be 1111 1110 but instead I get int (?) with value of 1 1111 1110 . 我期待结果是1111 1110但我得到int (?),值为1 1111 1110

How can the bits of an unsigned char be shifted to the left so that bits are truncated and the result is 1111 1110? 如何将无符号字符的位移到左侧,以便截断位,结果为1111 1110?

What I'm trying to do is to read series of bytes and interpret them as integers of varying lengths (1-32 bits). 我要做的是读取一系列字节并将它们解释为不同长度(1-32位)的整数。

F0        F5
1111 0000 1111 0101 

could be 可能

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

Has this something to do with the fact that arithmetic is not done with types smaller than int? 这与使用小于int的类型进行算术这一事实有关吗?

Quoting some draft of the 2011 standard: 引用2011年标准的一些草案:

5.8 Shift operators [expr.shift] 5.8移位运算符[expr.shift]

... ...

The operands shall be of integral or unscoped enumeration type and integral promotions are performed. 操作数应为整数或无范围的枚举类型,并执行整体促销。 The type of the result is that of the promoted left operand. 结果的类型是提升的左操作数的类型。

and

4.5 Integral Promotions [conv.prom] 4.5积分促销[conv.prom]

A prvalue of an integer type other than bool, char16_t, char32_t, or wchar_t whose integer conversion rank (4.13) is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; 如果int可以表示源类型的所有值,则除了bool,char16_t,char32_t或wchar_t之外的整数类型的prvalue(整数转换等级(4.13)小于int的等级)可以转换为int类型的prvalue ; otherwise, the source prvalue can be converted to a prvalue of type unsigned int 否则,源prvalue可以转换为unsigned int类型的prvalue

... ...

So, value is promoted to int , and the type of value << shift is the type of the promoted left operand, ie int . 因此, value被提升为intvalue << shift的类型value << shift是提升的左操作数的类型,即int

You can achieve your desired result one of these ways: 您可以通过以下方式之一获得所需的结果:

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

Just cast it back to an unsigned char: 只需将其强制转换为unsigned char:

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

Or, use bitwise-AND: 或者,使用按位AND:

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

You could mask the bits you're interested in: 你可以掩盖你感兴趣的位:

(value << shift) & 0xff

What you are seeing is a result of integer promotion, and is a part of the language. 您所看到的是整数提升的结果,并且是语言的一部分。 Imagine you're composing a 16-bit integer from 2 8-bit ones - you wouldn't want to manually promote to a higher width integer to get the high and low bits into the right place, right? 想象一下,你正在从2个8位整数组成一个16位整数 - 你不想手动提升到更高的宽度整数,以便将高位和低位放到正确的位置,对吧?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM