位移 - 移位移位值

时间:2012-07-25 19:06:00

标签: c++ arduino bit-manipulation bit-shift shift

我试图做一个更长的功能,但它的行为非常奇怪。我试图找出问题所在,我已经找到了这个有缺陷的部分。

这个程序是为Arduino制作的,但这种现象可能出现在其他环境中。我试图进行大量搜索但我找不到解决方案。

所以,我的马车部分:

为什么这两个代码不能给出相同的结果?
如何在没有额外变量的情况下构造单线函数 但是像“代码1”一样的操作?

结果:

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

源代码:


代码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(){
}

它给出: 0b00101100


代码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(){
}

它给出: 0b01101100


3 个答案:

答案 0 :(得分:5)

通过使用0xFF屏蔽来删除额外的位:

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

您也可以在移位序列后关闭高三位:

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

根据语言规范,默认的整数提升应用于移位前的移位操作数,操作的结果是第一个操作数的提升类型。

  

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

如果整数类型适合int,则int是促销的结果。向左移动时,最重要的位“溢出”到int的上半部分。您的第一个片段通过分配回byte来切断它们;您可以通过使用0xFF屏蔽结果来获得相同的结果。

Link to ideone

答案 1 :(得分:3)

如果byteuint8_t(感谢Fernandes先生!),(value << 3)的结果比byte更宽。更确切地说,value在转变发生之前被提升为更宽的类型,结果是更宽的类型。要获取代码1的行为,您可以更改代码2来执行此操作:

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

这模仿了代码1中带有强制转换的buffer的中间分配。

答案 2 :(得分:2)

我认为您的byte是一些小于int的无符号整数类型。

在将所有“较小”操作数隐式转换(提升)到类型int之后,C ++中的大多数算术运算都在int类型的域中执行。

出于这个原因,你的第一组轮班相当于

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

而你的第二组如果轮班相当于

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

在第一个变体中,在byte移位期间移位到<< 3类型范围之外的任何位在中间转换和分配到buffer期间都会丢失。在第二个变体中,所有计算都在int的范围内执行,因此不会丢失任何内容。

如果您希望第二个变体产生与第一个变体相同的结果,则需要明确“截断”中间偏移结果

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