C++ C+中的双重否定+;

C++ C+中的双重否定+;,c++,boolean,C++,Boolean,我刚进入一个有着巨大代码库的项目 我主要处理C++,他们编写的很多代码都使用双布尔逻辑来代替它们的布尔逻辑。p> if (!!variable && (!!api.lookup("some-string"))) { do_some_stuff(); } 我知道这些人都是聪明的程序员,很明显他们这样做不是偶然的 我不是经验丰富的C++专家,我唯一的猜测是为什么他们要绝对肯定,被评估的值是实际的

我刚进入一个有着巨大代码库的项目

<>我主要处理C++,他们编写的很多代码都使用双布尔逻辑来代替它们的布尔逻辑。p>
 if (!!variable && (!!api.lookup("some-string"))) {
       do_some_stuff();
 }                                   
我知道这些人都是聪明的程序员,很明显他们这样做不是偶然的

<>我不是经验丰富的C++专家,我唯一的猜测是为什么他们要绝对肯定,被评估的值是实际的布尔表示。所以他们对它求反,然后再次求反,使它回到实际的布尔值


这是正确的,还是我遗漏了什么?

这是一个转换为布尔值的技巧。

是运算符!超载?

如果不是,他们可能这样做是为了在不产生警告的情况下将变量转换为bool。这绝对不是一种标准的做事方式。

是的,这是正确的,不,你没有遗漏什么<代码>是到bool的转换。有关更多讨论,请参阅。

这是一种避免写入(变量!=0)的技术,即从任何类型转换为布尔值

像这样的IMO代码在需要维护的系统中没有位置——因为它不是立即可读的代码(因此首先是一个问题)


代码必须清晰易读,否则会给未来留下时间债务,因为理解一些不必要的复杂内容需要时间。

编码人员认为它会将操作数转换为bool,但由于&&的操作数已经隐式转换为bool,这是完全多余的。

这是正确的,但在C中,这里没有意义--“if”和“&&&”将以相同的方式处理表达式,而不使用“!!”

我想,C++中的原因是,& &可能会被重载。但是,我们也可以,因此,如果不查看
变量
api.call类型的代码,就不能保证得到bool。也许有更多C++经验的人可以解释;也许这是一种纵深防御措施,而不是一种保证。

如前所述,如果操作员过载起作用,这可能很重要。否则,在C/C++中,这并不重要,除非您正在执行以下操作之一:

  • 直接比较
    true
    (或者在C语言中类似于
    true
    宏),这几乎总是一个坏主意。例如:

    if(api.lookup(“某些字符串”)==true){…}

  • 您只需要将某些内容转换为严格的0/1值。在C++中,对<代码> BoOL <代码>的赋值将隐式地执行(对于那些隐含转换为<代码> Boo.<代码>的内容)。在C语言中,或者如果您处理的是非布尔变量,这是我见过的习惯用法,但我更喜欢
    (some_variable!=0)
    变体


我认为在一个更大的布尔表达式的上下文中,它只会把事情弄得一团糟。

也许程序员是这样想的


!!我的答案是布尔值。在上下文中,它应该是布尔型的,但我只是喜欢砰砰的一声来确定,因为从前有一个神秘的虫子咬了我,砰砰的一声,我把它杀死了。

在某些上下文中,它实际上是一个非常有用的成语。以这些宏为例(以Linux内核为例)。对于GCC,它们的实现如下所示:

#define likely(cond)   (__builtin_expect(!!(cond), 1))
#define unlikely(cond) (__builtin_expect(!!(cond), 0))
他们为什么要这样做?GCC的
\uuu内置\uExpect
将其参数视为
long
,而不是
bool
,因此需要某种形式的转换。因为他们在编写这些宏时不知道cond是什么,所以最普遍的做法是简单地使用
习语

通过与0进行比较,他们可能会做同样的事情,但在我看来,实际上做双重否定更简单,因为这是C最接近布尔的一个类型转换


此代码也可用于C++中。这是一个最小公分母的东西。如果可能的话,在C和C++中都做什么。

< p>它一边运行编译器警告。试试这个:

int _tmain(int argc, _TCHAR* argv[])
{
    int foo = 5;
    bool bar = foo;
    bool baz = !!foo;
    return 0;
}

“bar”行在MSVC++上生成一个“强制值bool'true'或'false'(性能警告)”,但“baz”行可以很好地通过。

如果变量是对象类型,它可能有一个!操作符定义了但没有强制转换为布尔(或者更糟的是隐式转换为不同语义的int)。调用“两次操作符”会导致转换成BoL,即使在奇怪的情况下也能工作。

<代码>!!< /COD>用于处理没有布尔类型的原始C++(如C也没有)。
示例问题:

if(condition)
内部,
condition
需要计算为某种类型,如
double、int、void*
等,但不能计算为
bool
,因为它还不存在

假设存在一个类
int256
(一个256位整数),并且所有整数转换/强制转换都被重载

int256 x = foo();
if (x) ...
为了测试
x
是否为“真”或非零,
if(x)
x
转换为某个整数,然后评估
int
是否为非零。
(int)x
的典型重载将仅返回
x
的lsbit,如果(x)
仅测试
x
的lsbit

< C++ >有<代码> >代码>运算符。重载<代码>!x>代码>通常会对<代码> x>代码>的所有位进行评价。因此,返回到非倒相逻辑<代码>(如果!x)< /代码>。


Ref

传统C开发人员没有布尔类型,因此他们通常
#定义TRUE 1
#定义FALSE 0
,然后使用任意数字数据类型进行布尔比较。现在我们有了
bool
,当某些类型的赋值和比较混合使用num进行时,许多编译器会发出警告eric类型和Boolean类型。这两种用法在处理遗留代码时最终会发生冲突

为了解决这个问题,一些
// operator bool version
  class Testable {
    bool ok_;
  public:
    explicit Testable(bool b=true):ok_(b) {}

    operator bool() const { // use bool conversion operator
      return ok_;
    }
  };
Testable test;
  if (test) 
    std::cout << "Yes, test is working!\n";
  else 
    std::cout << "No, test is not working!\n";
bool operator!() const { // use operator!
    return !ok_;
  }
  Testable test;
  if (!!test) 
    std::cout << "Yes, test is working!\n";
  if (!test2) {
    std::cout << "No, test2 is not working!\n";