我刚刚进入一个拥有相当庞大代码库的项目.
我主要处理C++,他们编写的很多代码都使用布尔逻辑的双重否定.
if (!!variable && (!!api.lookup("some-string"))) {
do_some_stuff();
}
Run Code Online (Sandbox Code Playgroud)
我知道这些人都是聪明的程序员,很明显他们不会偶然这样做.
我不是经验丰富的C++专家,我唯一猜测他们这样做的原因是他们想要绝对肯定被评估的值是实际的布尔表示.所以他们否定它,然后再次否定它以使其恢复到它的实际布尔值.
这是正确的,还是我错过了什么?
Don*_*eld 114
这是转换为布尔的技巧.
Tom*_*rta 69
在某些情况下,它实际上是一个非常有用的习惯用语.拿这些宏(来自Linux内核的例子).对于海湾合作委员会,它们的实施如下:
#define likely(cond) (__builtin_expect(!!(cond), 1))
#define unlikely(cond) (__builtin_expect(!!(cond), 0))
Run Code Online (Sandbox Code Playgroud)
他们为什么要这样做?GCC的__builtin_expect对待它的参数long,而不是bool,所以需要有某种形式的转换.由于他们不知道什么cond时候他们正在编写这些宏,所以最简单的就是使用这个!!成语.
他们可能通过与0比较来做同样的事情,但在我看来,做双重否定实际上更直接,因为那是最接近C的铸造到布尔的.
这段代码也可以在C++中使用......它是最常见的分母.如果可能的话,在C和C++中做什么都可以.
fiz*_*zer 50
编码器认为它会将操作数转换为bool,但由于&&的操作数已经隐式转换为bool,因此它完全是多余的.
Ric*_*son 11
这是一种避免写入的技术(变量!= 0) - 即从任何类型转换为bool.
像这样的IMO代码在需要维护的系统中没有位置 - 因为它不是立即可读的代码(因此首先是问题).
守则必须清晰易读 - 否则你将为未来留下一段时间的债务遗产 - 因为需要时间来理解一些不必要的错综复杂的东西.
它侧重于编译器警告.试试这个:
int _tmain(int argc, _TCHAR* argv[])
{
int foo = 5;
bool bar = foo;
bool baz = !!foo;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
'bar'行在MSVC++上生成"强制值'bool'true'或'false'(性能警告)",但'baz'行悄然通过罚款.
传统的C开发人员没有布尔类型,所以他们经常#define TRUE 1和#define FALSE 0再使用任意的数字数据类型布尔比较。现在我们有了bool,当使用数字类型和布尔类型的混合进行某些类型的赋值和比较时,许多编译器会发出警告。在处理遗留代码时,这两种用法最终会发生冲突。
为了解决这个问题,一些开发人员使用以下布尔标识:!num_valuereturn bool trueif num_value == 0; false除此以外。!!num_value返回bool false如果num_value == 0; true除此以外。单个否定足以转换num_value为bool; 然而,双重否定是恢复布尔表达式的原始意义所必需的。
这种模式被称为惯用语,即熟悉该语言的人常用的东西。因此,我并不像我那样认为它是一种反模式static_cast<bool>(num_value)。强制转换很可能会给出正确的结果,但是一些编译器随后会发出性能警告,因此您仍然必须解决这个问题。
解决这个问题的另一种方法是说,(num_value != FALSE). 我也同意,但总而言之,!!num_value它不那么冗长,可能更清晰,并且第二次看到它时不会感到困惑。
| 归档时间: |
|
| 查看次数: |
30367 次 |
| 最近记录: |