为什么以下按位运算会返回意外结果?

时间:2013-04-23 02:10:58

标签: c

3位最多可以容纳7(4 + 2 + 1)。我正在尝试使用按位运算来计算它。

3 is 0b011 
~3 is 0b100

按位进行或我希望0b111(即7)。相反,我得到

int result = (~3) | 3;
printf("%i\n", result);
  

-1

我做错了什么?

5 个答案:

答案 0 :(得分:6)

您正在做的一切正确:N | ~N会产生一个二进制表示的数字,包含所有数字。这个数字在two's compliment中以负数表示为-1

答案 1 :(得分:4)

int的宽度是多少?你似乎认为它有三位宽。当然不正确!再猜。什么是~0u?试试printf("%u\n", ~0u);。那么~1u呢? ......和~2u?你注意到一种模式吗?

请注意u后缀,它告诉编译器它是unsigned字面值。您无法使用带有~运算符的有符号整数类型...嗯,您可以,但根据n1570的6.2.6.2,您可能遇到陷阱表示和负零。 .PDF。使用陷阱表示是未定义的行为。 可能在您的系统上工作,但只是巧合。你想依靠巧合吗?

同样,我建议使用%u指令来打印unsigned值,因为%d会根据n1570.pdf的7.21.6.1p29产生未定义的行为。

答案 2 :(得分:0)

当您执行~3时,您正在反转组成3的位 - 因此您将0000 0000 0000 0000 0000 0000 0000 0011转换为1111 1111 1111 1111 1111 1111 1111 1100。由于设置了高位,因此将其解释为负数 - 所有1均为-1,小于-2,少于-3,依此类推。这个数字是-4的带符号32位整数。

如果二进制或者这个为3,则得到全1(根据定义) - 这是-1的带符号32位整数。

您唯一的问题是您认为自己使用的是3位数字,但实际上是在处理32位数字。

答案 3 :(得分:0)

在代码中执行此操作后

  int result = (~3) | 3;

添加此行

   result= result & 0x07

这将为您提供您期望的答案。

答案 4 :(得分:0)

#include <stdio.h>

int main (){
    unsigned d3 = 0b011;
    unsigned invd3 = ~d3;
    unsigned d4 = 0b100;
    unsigned result = d3 | invd3;
    printf("%X\n", result);//FFFFFFFF
    result = d3 | d4;
    printf("%X\n", result);//7
    return 0;
}
相关问题