根据条件应用/移除位掩码

3
我希望您能简化以下表达式(block 是一个整数,可以是 01):
if (block)
    opts = opts & ~O_NONBLOCK;
else
    opts = opts | O_NONBLOCK;

这是我想出来的东西:

opts = block ? opts & ~O_NONBLOCK : opts | O_NONBLOCK;

然而,我相信有更聪明的方法来做到这一点。


1
调试比一开始编写代码难两倍。如果你尽可能聪明地编写代码.. :-)) - cnicutar
你说得对!我不认为我会使用“最聪明”的解决方案,但实际上我只是好奇。 - watain
@shiplu.mokadd.im 它会根据 block 是否设置来清除或设置 O_NONBLOCK 位。 - Daniel Fischer
3个回答

2
这个怎么样?
opts = (opts & ~O_NONBLOCK) | (!block * O_NONBLOCK);

我更喜欢你的第一个选项比这个有些神秘的解决方案更加明确易懂。


他已经修复了代码,使用!block代替。 - Thomas
我想我正在寻找这样的东西。真的很神秘,那是肯定的! - watain
可以用这个方法,不过可能会引入一个分支。 (我不知道指令集。如果有专门的指令,那可能比“1-block”更快。) - Daniel Fischer
我接受了你的解决方案,因为它似乎是最简洁的。然而,我还是打算继续使用带有复合赋值的 if/else 变量。无论如何,还是谢谢! - watain
@PascalCuoq 我的gcc(4.6.2,在x86_64 Linux上)可以产生两种乘法。如果block是一个int,我从clang得到cmpl; sbbl; andl,而使用!block则会得到相同的结果。如果block是一个bool,gcc仍然会产生一个imull,但是clang会为两种变量都执行xorl $-2; incl; andl(聪明;)。不知道哪个更快。 - Daniel Fischer
显示剩余2条评论

2

你的第一个例子非常简单,肯定更好地解释了正在发生的事情。

如果出于某些原因你渴望打少一些字符,我想你可能会使用赋值运算符:

if (block)
    opts &= ~O_NONBLOCK;
else
    opts |= O_NONBLOCK;

如果可以避免的话,我肯定不会使用三元运算符。

1
这绝对是我首选的路线。一种选择是:opts &= ~ O_NONBLOCK; if (!block) opts |= O_NONBLOCK; - 但这可能不是更好的选择。保持代码可读性比使其复杂要好得多。这甚至看起来都不像代码中的“热点路径”,所以我不会担心性能问题[尽管我认为它实际上并没有任何区别]。 - Mats Petersson

1
在第一个版本中,您还可以使用运算符的复合赋值版本。
if (block)
    opts &= ~O_NONBLOCK;
else
    opts |= O_NONBLOCK;

:)

虽然我通常更喜欢在可能和适当的情况下使用 ?: 运算符而不是 if。但在这种特定情况下,很难说哪个看起来更优雅。


通常,我也更喜欢使用?:运算符,但由于某种原因,这个解决方案似乎更加优雅和可读。 - watain

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