我刚刚进入一个拥有相当庞大代码库的项目.
我主要处理C++,他们编写的很多代码都使用布尔逻辑的双重否定.
if (!!variable && (!!api.lookup("some-string"))) { do_some_stuff(); }
我知道这些人都是聪明的程序员,很明显他们不会偶然这样做.
我不是经验丰富的C++专家,我唯一猜测他们这样做的原因是他们想要绝对肯定被评估的值是实际的布尔表示.所以他们否定它,然后再次否定它以使其恢复到它的实际布尔值.
这是正确的,还是我错过了什么?
这是转换为布尔的技巧.
在某些情况下,它实际上是一个非常有用的习惯用语.拿这些宏(来自Linux内核的例子).对于海湾合作委员会,它们的实施如下:
#define likely(cond) (__builtin_expect(!!(cond), 1)) #define unlikely(cond) (__builtin_expect(!!(cond), 0))
他们为什么要这样做?GCC的__builtin_expect
对待它的参数long
,而不是bool
,所以需要有某种形式的转换.由于他们不知道什么cond
时候他们正在编写这些宏,所以最简单的就是使用这个!!
成语.
他们可能通过与0比较来做同样的事情,但在我看来,做双重否定实际上更直接,因为那是最接近C的铸造到布尔的.
这段代码也可以在C++中使用......它是最常见的分母.如果可能的话,在C和C++中做什么都可以.
编码器认为它会将操作数转换为bool,但由于&&的操作数已经隐式转换为bool,因此它完全是多余的.
是的,这是正确的,不,你不会错过任何东西. !!
是对bool的转换.有关更多讨论,请参阅此问题.
这是一种避免写入的技术(变量!= 0) - 即从任何类型转换为bool.
像这样的IMO代码在需要维护的系统中没有位置 - 因为它不是立即可读的代码(因此首先是问题).
守则必须清晰易读 - 否则你将为未来留下一段时间的债务遗产 - 因为需要时间来理解一些不必要的错综复杂的东西.
它侧重于编译器警告.试试这个:
int _tmain(int argc, _TCHAR* argv[]) { int foo = 5; bool bar = foo; bool baz = !!foo; return 0; }
'bar'行在MSVC++上生成"强制值'bool'true'或'false'(性能警告)",但'baz'行悄然通过罚款.
是运营商!超载?
如果没有,他们可能会这样做,将变量转换为bool而不产生警告.这绝对不是一种标准的做事方式.