【问题标题】:What does return !!myVar mean?return !!myVar 是什么意思?
【发布时间】:2022-01-09 23:22:37
【问题描述】:

我正在阅读使用 glib 的 C 语言开放代码,我发现了类似的内容

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

我不明白那个双感叹号到底发生了什么。

【问题讨论】:

  • ! 是一个逻辑 not!! 是逻辑 not 应用了两次。这有效地将任何非零值转换为1
  • 这能回答你的问题吗? What does !! (bang bang) mean?
  • 什么是gboolean function()?即使在 80 年代,将函数命名为“函数”也被认为是不好的做法。但现在不是80年代了,你应该声明参数。
  • 我一直称之为“布尔归约”

标签: c unary-operator negation


【解决方案1】:

它与单个感叹号相同,两次。它两次否定一个值。

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    return !!myVar;
    

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

    函数体可以改写为:

    return globalVar1 || globalVar2  || globalVar3;
    

    更清楚地表达了意图。但是,|| 运算符确实涉及分支,因此编写的代码可能试图避免这种分支。

    不过,一般来说,编译器很擅长优化,所以这种微优化并不是真正必要的。

    【讨论】:

      【解决方案3】:

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

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

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

      5 逻辑否定运算符的结果!如果值为 0 它的操作数比较不等于0,如果它的操作数的值是1 比较等于 0。结果的类型为 int。表达式 !E 是 相当于 (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,否则返回1。

      你可以写在return语句中

      return myVar != 0;
      

      但是代码的作者决定写

      return !!myVar;
      

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

      这种使用否定运算符的“平衡行为”的目的是准确地返回 0 或 1。

      【讨论】:

      • @ikegami 谢谢。这是一个错字。:)
      【解决方案4】:

      如果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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-03
        • 2017-03-02
        • 2011-08-22
        • 1970-01-01
        • 2012-09-17
        • 2013-11-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多