C 仅使用位运算符实现逻辑求反(除了!)

C 仅使用位运算符实现逻辑求反(除了!),c,bit-manipulation,boolean-logic,negation,C,Bit Manipulation,Boolean Logic,Negation,~&^ |+>是我唯一可以使用的操作 在我继续之前,这是一个家庭作业问题,我已经被困在这个问题上很长时间了 我最初的想法是:我想!x可以用2的补码来做,也可以用它的加法逆来做。我知道这里可能有一个xor,但我真的不知道如何处理这个问题 请注意:我也不能使用条件句、循环、=等,只能使用上面提到的函数(按位) 例如: !0 = 1 !1 = 0 !anything besides 0 = 0 假设为8位无符号类型: ~(((x >> 0) & 1) | ((x >>

~&^ |+>
是我唯一可以使用的操作

在我继续之前,这是一个家庭作业问题,我已经被困在这个问题上很长时间了

我最初的想法是:我想!x可以用2的补码来做,也可以用它的加法逆来做。我知道这里可能有一个xor,但我真的不知道如何处理这个问题

请注意:我也不能使用条件句、循环、
=
等,只能使用上面提到的函数(按位)

例如:

!0 = 1
!1 = 0
!anything besides 0 = 0

假设为8位无符号类型:

~(((x >> 0) & 1)
| ((x >> 1) & 1) 
| ((x >> 2) & 1)
...
| ((x >> 7) & 1)) & 1

以下代码将任何1位复制到所有位置。这会将所有非零映射到
0xFFFFFFFF==-1
,同时将
0
保留在
0
。然后它添加1,将
-1
映射到
0
,将
0
映射到
1

x = x | x << 1  | x >> 1
x = x | x << 2  | x >> 2
x = x | x << 4  | x >> 4
x = x | x << 8  | x >> 8
x = x | x << 16 | x >> 16

x = x + 1
x=x | x>1
x=x | x>2
x=x | x>4
x=x | x>8
x=x | x>16
x=x+1

您只需执行~x&1,因为它为0生成1,为其他所有值生成0

假设32位无符号整数:

(((x>>1) | (x&1)) + ~0U) >> 31

应该对32位有符号整数x执行此操作

// Set the bottom bit if any bit set.
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;

x ^= 1;   // Toggle the bottom bit - now 0 if any bit set.
x &= 1;   // Clear the unwanted bits to leave 0 or 1.

假设
x
已签名,则需要为非零的任何数字返回0,为零返回1

在大多数实现中,有符号整数的右移通常是算术移位(例如,符号位被复制)。因此,右移位
x
31,其反移位31。其中一个是负数,因此右移31将是0xFFFFFFFF(当然,如果x=0,那么右移将产生0x0,这是您想要的)。你不知道x或它的否定是负数,所以只要把它们加在一起,你就会得到你想要的。下一步加1和你的好

实施:

int bang(int x) {
    return ((x >> 31) | ((~x + 1) >> 31)) + 1;
}

您真的希望它们直接计算为1和0,还是简单地计算为逻辑上的true和false?i、 e.
~0
是否可以接受为逻辑true?注意:
+
不是按位运算符。这种练习本质上没有意义,因为任何结果的使用都需要一个基本上与零比较的条件。我的答案是
if(var);else{/*你的代码在这里*/}
@R:诀窍是你不需要使用条件句,因为C没有
bool
。(例如,不用
return x!=0;
你可以说
return x;
假设他不需要
1
returned…这就是我想弄明白的。)@Mehrdad:C99确实有
bool
,但是,如果你不乐意说
\u Bool
,那么你必须包含
stdbool.h
才能得到它。你可以做
~x
@Chris Lutz:将0映射到-1,而不是所需的1。@Jay-做一个像
*(unsigned*)&i
这样的演员。将除0之外的所有数字转换为“正数”,然后减去1,这只会使0为负数,然后提取符号位。这可以简化为
(~(x>>1)+x)>>31
。我认为你应该取反,而不是加一。也就是说,
~((x>>31)|((~x+1)>>31))
。实际上,没有。添加1是正确的。我忘了
>
移位在C语言中是算术的,不是逻辑的。因此,
>31
-ing
10…00
将产生
11…11
,而不是
00…01