C - 三个字节到一个signed int

mul*_*iku 3 c twos-complement signed-integer

我有一个传感器,它以三个字节输出.我这样看了:

unsigned char byte0,byte1,byte2;

byte0=readRegister(0x25);
byte1=readRegister(0x26);
byte2=readRegister(0x27);
Run Code Online (Sandbox Code Playgroud)

现在我想将这三个字节合并为一个数字:

int value;
value=byte0 + (byte1 << 8) + (byte2 << 16);
Run Code Online (Sandbox Code Playgroud)

它给出了从0到16,777,215的值,但我期望从-8,388,608到8,388,607的值.我虽然int已经通过其实施签署了.即使我尝试定义它signed int value;仍然只给我正数.所以我想我的问题是如何将int转换为它的两个补码?

谢谢!

Gri*_*tov 7

您需要执行的操作称为符号扩展.你有24个有效位但需要32位有效位(注意你假设int是32位宽,这并不总是正确的;你最好使用int32_t定义的类型stdint.h).缺少8个顶部位应该是全部为正值的零或全部为负值.它由24位值的最高位定义.

int32_t value;
uint8_t extension = byte2 & 0x80 ? 0xff:00; /* checks bit 7 */
value = (int32_t)byte0 | ((int32_t)byte1 << 8) | ((int32_t)byte2 << 16) | ((int32_t)extension << 24);
Run Code Online (Sandbox Code Playgroud)

编辑:请注意,您不能将8位值移位8位或更多位,这是未定义的行为.你必须先把它变成更宽的类型.

  • 整数提升应用于`&lt;&lt;`的操作数;在 C 中你根本不能移动 8 位值,因为它首先会被提升为“int”或“unsigned int”。但是,您可能希望阻止它选择不适当的转换路径(例如,无符号操作数上的意外符号扩展)。 (2认同)
  • @GrigoryRechistov:这不是移位操作中对“char”的特殊处理。在 C 中,所有整数表达式(包括“_Bool”、“char”和“short”)在大多数上下文中都至少提升为“int”。 (2认同)