二进制数:+和|之间的奇怪差异

时间:2020-08-17 08:39:57

标签: c

我正在尝试使用c操纵二进制数。我发现下面的最少代码很奇怪。谁能告诉我“ +”和“ |”有什么区别这里?谢谢!

char next_byte1 = 0b11111111;
char next_byte2 = 0b11110101;
short a = (next_byte1 << 8) | next_byte2;
short b = (next_byte1 << 8) + next_byte2;
printf("a vs b is %d ~ %d.\n", a, b);

它显示:a vs b是-11〜-267,分别是0b11111111 11110101和0b1111111011110101。我对这个结果感到非常困惑。

3 个答案:

答案 0 :(得分:7)

您看到的问题是,在进行按位运算之前,next_byte2被符号扩展为完整的int,从而“破坏”了高字节。

进行位操作时,最好使用unsigned类型(实际上是使用unsigned的类型)。普通char类型可以是(通常是)带符号类型,因此最好避免用于这些用途。

答案 1 :(得分:6)

  • 永远不要将char用于二进制/按位算术,因为它具有实现定义的签名,并且可能为负数。通常,对默认的C类型使用stdint.h
  • 如果对char进行了签名,则在变量初始化期间,其内部的值最终将以二进制补码转换为-1。分别发生在next_byte1next_byte2上。
  • 每当在表达式中使用小整数类型时,通常会将其提升为带符号的int。因此,您的-1(0xFF)会变为-1(0xFFFFFFF),然后再离开班次。
  • 左移负操作数是未定义的行为,这意味着任何类型的错误都可能在您的程序中泛滥。在这种情况下会发生这种情况,因此无法保证结果。
  • 显然,在您的情况下,未定义的行为在您最终以二进制表示0xFFFFFF00的较大负数时表现出来。
  • |+之间的区别在于后者关心符号,因此,在+的情况下,您最终将负数加在一起,而在{{1}的情况下}二进制表示形式简单地进行或:运算。

您可以通过以下方式修复程序:

|

现在#include <stdio.h> #include <stdint.h> int main(void) { uint8_t next_byte1 = 0xFF; uint8_t next_byte2 = 0xF5; uint16_t a = (next_byte1 << 8) | next_byte2; uint16_t b = (next_byte1 << 8) + next_byte2; printf("a vs b is %d ~ %d.\n", a, b); } |可以按预期工作。

答案 2 :(得分:0)

两个答案都可以解决您的问题。我只想在'|'周围添加清晰度和“ +”运算符。

  • '|'是按位或运算符

  • '+'是加法运算符,它转换为包含性OR
    CARRY传播的多位数字运算符。

虽然它们在某些情况下可能会产生与您的示例相同的结果,但是它们不是同一运算符,并且通常不应期望得到相同的结果。

相关问题