使用位运算符的条件语句

13

我看到这个问题已经被问过了,但是答案有点模糊和无用。好的,我需要使用 "& ^ ~ ! + | >> <<" 来实现一个C语言表达式。

这个表达式需要类似于:a ? b : c

据我所知,表达式需要看起来像:

return (a & b) | (~a & c)

当a = 0时,这个表达式可以工作,因为与b进行and运算将得到零,然后或运算将返回右边的表达式(~a&c),这能够工作是因为 ~0会得到所有1,将c与所有1进行and运算将返回c。

然而,当a>0时,这个表达式就不再适用了。能否有人尝试解释一下为什么,或者如何解决这个问题?

2个回答

21

我会使用 !!aa 转换为布尔型,以获取 0 或 1。 x = !!a

然后我会使用二进制补码将其取反。由于您没有一元负号可用,因此可以使用二进制补码取反的定义:反转位,然后加一:y = ~x + 1。这将给出全部位清空或全部位设置的结果。

然后我会直接使用一个变量 y & b 进行逻辑与运算,并使用另一个变量的反义词进行逻辑与运算:~y & c。其中一个表达式将得到 0,而另一个将返回原始变量。当我们将它们进行逻辑或运算时,0 不会产生影响,因此我们将获得原始变量,且不会发生更改。


这实际上是完美的。那么为什么加一会使得所有位都被设置或清除了呢?我理解需要这样做的原因,但我不理解它是如何发生的。 - atb
如果我们从0开始,那么翻转二进制位会得到全1。当我们加1时,所有的位都变回0(并且进位被设置,但我们忽略它)。如果我们从1开始,翻转二进制位会得到111...10。加1会将最后一个0变成1,因此所有位现在都是1。 - Jerry Coffin
“y = ~x + 1” 这部分让我感到困惑;最终我发现它是由于整数溢出的情况下 x = 0,但这并不明显。对我来说更清晰的解决方案是先通过左移将 lsb 移动到 msb(00000001 => 10000000),然后通过右移复制 msb: “y = (x << 31) >> 31”。 - Anton Sergeyev

3
换句话说,如果 afalse(即 0),则需要将所有位设置为 0;如果 a 是真的(即 a > 0),则需要将所有位设置为 1。针对前者情况,已经为您完成了工作;针对后者情况,请尝试计算表达式 ~!1 的结果。

起初我也是这么想的。~!1 会给出全是1,非常完美。但是,如果我执行 ~!a,而且 a = 0,那么 ~!0 就会给我 1110,所以我不确定接下来该怎么做 /: - atb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接