return !!myVar 是什么意思?

What does return !!myVar mean?

我正在阅读一个使用 glib 的 C 语言的开放代码,我发现了类似这样的东西

gboolean function()
{
  guint myVar = 0;
  myVar = (!!globalVar1 + !!globalVar2 + !!globalVar3);
  return !!myVar;
}

我不明白那个双感叹号到底是怎么回事。

和一个感叹号一样,两次。它两次否定一个值。

这具有将所有整数转换为 0(如果它们已经是 0)或 1(如果它们是任何非零值)

一元 ! 运算符执行逻辑 NOT 运算。如果其操作数不为零,则计算结果为 0。如果其操作数为 0,则计算结果为 1。

当它们两个像这样放在一起时,它将操作数规范化为布尔值。因此,如果操作数为 0,则结​​果为 0,如果操作数为非零,则结果为 1。

在较大表达式的上下文中:

myVar  = (!!globalVar1 + !!globalVar2 + !!globalVar3);

这会将 myVar 设置为 0 到 3 之间的值。然后是:

return !!myVar;

将该值标准化为 0 或 1。因此最终结果是,如果 3 个变量中的任何一个不为零,则返回 1,否则返回 0。

函数体可以重写为:

return globalVar1 || globalVar2  || globalVar3;

哪个更清楚地表达了意图。然而,|| 运算符确实涉及分支,因此编写的代码可能试图避免该分支。

虽然一般来说,编译器非常擅长优化,所以这样的微优化并不是真正必要的。

让我们首先考虑一下这个说法

myVar = (!!globalVar1 + !!globalVar2 + !!globalVar3);

现在根据 C 标准(6.5.3.3 一元算术运算符)

5 The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E)

例如 如果你有这样的变量

int x = 10;

然后将运算符!应用到变量!x你会得到0.第二次应用运算符!!x你会得到1.如果写是一样的x != 0.

因此,如果操作数 globalVar1globalVar2globalVar3 中至少有一个,则赋值结果为非零值。不等于 0.

上面的语句可以改写成下面的方式

myVar = ( ( globalVar1 != 0 ) + ( globalVar2 != 0 ) + ( globalVar3 != 0 ) );

赋值的结果可以是0(如果所有操作数都等于0),或者1(如果只有一个操作数不等于0),或者2(如果两个操作数都等于0),或者3(如果所有操作数都等于 0)。

如果至少一个操作数不等于 0 或 1,则函数需要 return1。否则

你可以只写在return声明

return myVar != 0;

但是代码的作者决定写

return !!myVar;

看来他很喜欢否定运算符!.:)

这种使用否定运算符的“平衡行为”的目的是 return 恰好是 0 或 1。

如果 val 为零,

!!val 给出 0,如果 val 不为零,则 1

用法示例:

//function counting non zero elelemnts of array
size_t countNonZero(const int *array, size_t size)
{
    size_t count = 0;
    while(size--)
        count += !!*array++;
    return count;
}

在您的示例中,不需要 !! 运算符,因为在 C 中任何非零值都被视为 true。应该使用简单的 || 运算符。

该函数应重写为

gboolean function()
{
  return globalVar1 || globalVar2 || globalVar3;
}