3

我试图做一个更长的功能,但它的行为很奇怪。我曾试图找出问题所在,但我已经能够找到错误的部分。

该程序是为 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


4

3 回答 3

5

通过使用以下掩码删除额外的位0xFF

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

您还可以在移位序列之后修剪高三位:

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

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

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

如果整数类型可以放入 中intint则为提升的结果。当您向左移动时,最高有效位“溢出”到int. byte您的第一个片段通过分配回;来切断它们。您可以通过使用 屏蔽结果来获得相同的结果0xFF

链接到 ideone

于 2012-07-25T19:13:46.430 回答
3

If byte is a uint8_t (thanks Mr. Fernandes!), the result of (value << 3) is wider than a byte. More precisely, value is promoted to a wider type before the shift occurs, and the result is that wider type. To get the behavior of Code 1, you can change Code 2 to do this:

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

This mimics the intermediate assignment to buffer in Code 1 with a cast.

于 2012-07-25T19:11:59.920 回答
2

我假设你byte是一些小于的无符号整数类型int

C++ 中的大多数算术运算都是在inttype 域中执行的,毕竟“较小的”操作数被隐式转换(提升)为 type int

因此,您的第一组班次相当于

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

而你的第二组 if shifts 相当于

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

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

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

result = ((byte) (value << 3) >> 2);
于 2012-07-25T19:15:44.323 回答