【问题标题】:I can't understand why I get this result when I bitwise OR a short and char我不明白为什么当我按位或短和字符时会得到这个结果
【发布时间】:2017-01-23 23:53:26
【问题描述】:

有人能解释一下为什么当我对两个数字进行按位或运算时会得到这个结果吗?我真的很困惑。

signed char signedChar = -64;       // This is now -64, or 1100 0000
unsigned char unsignedChar = signedChar; // This is now 196, or 1100 0000 (The same)

short signedShort = 0;     // This is now 0000 0000 0000 0000
signedShort |= signedChar;   // This is now -64, not 196 

我预期会发生的是,我对 signedShort 和 signedChar 进行了运算,即:

0000 0000 0000 0000 or'ed with
          1100 0000
0000 0000 1100 0000 result 
equalling 196.

但我得到了 -64

为什么这个 OR 操作会在开头添加一个?我完全期待一些不同的东西。

谢谢。

【问题讨论】:

  • 算术转换?
  • 因为符号扩展。
  • @Kerrek 哦,所以你是说在它执行操作之前,它会将 char 提升为 short,然后 short 有一个前导 1,然后按位 OR?有什么方法可以将这些位添加到短片中?
  • 比这更微妙。事实上,一切都被提升为int。通常你应该 a) 使用无符号类型,然后 b) 截断结果。
  • 与零进行或运算不会改变其值。所以如果你用 -64 或 0,你得到 -64。这与signedShort = signedChar; 没有什么不同。

标签: c++ c bit-manipulation bits


【解决方案1】:

表达式signedShort |= signedChar;被解释为

signedShort = signedShort | signedChar;

| 运算符的两个操作数都提升为 int,对这些提升的值执行按位或运算,并将结果转换为目标的类型 short

因此signedChar-64 的值被扩展为具有相同值的int。对0 进行或运算不会更改该值。将其转换为short 也保留该值,因为-64short 的范围内,所以结果为-64

请注意,这不依赖于整数的实际表示。您在问题中假设 2s 补码,但它会产生与符号 + 幅度或 1s 补码相同的结果。

【讨论】:

    【解决方案2】:

    带负值的有符号类型将用 1 扩展。无符号类型将用零扩展。

    您的 unsigned char 被提升为已签名,因为这是您正在执行操作的内容。

    签名是未签名的提升

    在你的例子中:

    0000 0000 0000 0000 or'ed with
    1111 1111 1100 0000
    1111 1111 1100 0000 result
    

    【讨论】:

    • 您的意思是带负号的签名类型将扩展为负号。否则,如果值在扩展时突然开始变异,那将是一团糟。
    【解决方案3】:

    这就是Two's complement 算术的基本原理。为了保留值的符号,在转换过程中应用了特殊操作 Sign extension

    让我们举一个更简单的 -10 例子:

    signed char signedChar = -10; // bits: 11110110b
    signed short signedShort = signedChar; // bits: 1111111111110110b
    

    为什么不像您预期​​的那样 1000000000000110b?因为 1000000000000110b 在二进制补码中是 -32762 :-(

    【讨论】:

    • 该代码不打印带符号的值,而是调用未定义的行为。 printf 期望 unsigned int 对应 %x,但您传递了 int
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 2013-11-06
    • 2012-05-01
    • 2016-02-03
    • 2022-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多