简体   繁体   English

移位-移位值

[英]bit shift - shifting a shifted value

I have tried to make a longer function but it has acted very weird. 我试图做一个更长的功能,但是它表现得很奇怪。 I had tried to isolate the problem and I have been able to find the buggy part. 我试图找出问题所在,并且能够找到越野车部分。

This program made for an Arduino but this phenomenon probably appear in other environment. 该程序是为Arduino开发的,但是这种现象可能出现在其他环境中。 I have tried to make a lot of searches but I cannot find the solution. 我试图进行大量搜索,但找不到解决方案。

So, my buggy part: 因此,我的越野车部分:

Why do not these two codes give the same result? 为什么这两个代码不能给出相同的结果?
How can I construct a one line function without extra variable 如何构造没有额外变量的单行函数
but same operation like "Code 1"? 但是像“代码1”一样的操作?

Results: 结果:

  • Code 1: 0b00101100 代码1:0b00101100
  • Code 2: 0b01101100 代码2:0b01101100

Source codes: 源代码:


Code 1: (correct operation but not one line) 代码1 :(正确操作,但不是一行)

#include <binary.h>

const byte value=B00110110;
byte buffer,result;

void setup(){
  Serial.begin(115200);

  buffer = (value << 3);
  result = (buffer >> 2);

  Serial.println(result,BIN);
}

void loop(){
}

It gives: 0b00101100 它给出了: 0b00101100


Code 2: (incorrect operation but one line) 代码2 :(操作错误,但只有一行)

#include <binary.h>

const byte value=B00110110;
byte result;

void setup(){
  Serial.begin(115200);

  result = ((value << 3) >> 2);

  Serial.println(result,BIN);
}

void loop(){
}

It gives: 0b01101100 它给出了: 0b01101100


Remove the extra bits by masking with 0xFF : 通过使用0xFF屏蔽来删除多余的位:

result = (((value << 3) & 0xFF) >> 2);

You can also trim the upper three bits off after the sequence of shifts: 您还可以在移位顺序后将高三位修剪掉:

result = 0x1F & ((value << 3) >> 2);

According to the language specification, default integer promotions are applied to shift operands before shifting, and the result of the operation is the promoted type of the first operand. 根据语言规范,在移位之前将默认整数提升应用于移位操作数,并且运算结果是第一个操作数的提升类型。

5.8.1 The operands shall be of integral or enumerated type and integral promotions are performed. 5.8.1操作数应为整数或枚举类型,并执行整数提升。 The type of the result is that of the promoted left operand. 结果的类型是提升后的左操作数的类型。

If an integral type can fit in an int , then int is the result of the promotion. 如果整数类型可以适合int ,则int是提升的结果。 When you shift left, the most significant bits "spill" into the upper part of the int . 当您向左移动时,最高有效位会“溢出”到int的上部。 Your first snippet cuts them off by assigning back to byte ; 您的第一个片段通过分配回byte来切断它们; you can achieve the same result by masking the result with 0xFF . 您可以通过使用0xFF屏蔽结果来获得相同的结果。

Link to ideone . 链接到ideone

If byte is a uint8_t (thanks Mr. Fernandes!), the result of (value << 3) is wider than a byte . 如果byteuint8_t (感谢Fernandes先生!),则(value << 3)的结果比byte宽。 More precisely, value is promoted to a wider type before the shift occurs, and the result is that wider type. 更确切地说,在转变发生之前, value被提升为更广泛的类型,结果就是那个更广泛的类型。 To get the behavior of Code 1, you can change Code 2 to do this: 要获取代码1的行为,可以更改代码2来执行以下操作:

result = (static_cast<byte>(value << 3) >> 2);

This mimics the intermediate assignment to buffer in Code 1 with a cast. 这样可以通过强制转换模仿代码1中buffer的中间分配。

I assume that your byte is some unsigned integral type smaller than int . 我假设您的byte是一些小于int无符号整数类型。

Most arithmetic operations in C++ are performed in the domain of int type, after all "smaller" operands are implicitly converted ( promoted ) to type int . 用C大部分算术运算++中的域执行int促进 )型,毕竟“较小”操作数被隐式转换为类型int

For this reason, your first group of shifts is equivalent to 因此,您的第一组班次等于

buffer = (byte) ((int) value << 3);
result = (byte) ((int) buffer >> 2);

while your second group if shifts is equivalent to 而第二组如果班次等于

result = (byte) (((int) value << 3) >> 2);

In the first variant, any bits that get shifted outside the range of type byte by the << 3 shift are lost during intermediate conversion and assignment to buffer . 在第一种变体中,在中间转换和分配给buffer过程中,所有被移位超出byte类型范围<< 3移位的位都将丢失。 In the second variant all calculations are performed within the range of int , so nothing is lost. 在第二个变体中,所有计算都在int范围内执行,因此不会丢失任何内容。

If you want your second variant to produce the same results as the first, you need to explicitly "truncate" the intermediate shift result 如果您希望第二个变体产生与第一个变体相同的结果,则需要显式“截断”中间移位结果

result = ((byte) (value << 3) >> 2);

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

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