【问题标题】:Compound statement to change value after returning it?返回后更改值的复合语句?
【发布时间】:2014-02-25 14:52:07
【问题描述】:

我想知道返回值后是否可以更改变量?

有问题的函数是一个用于私有布尔标志变量的简单 get 函数。我希望读取这个标志是破坏性的,所以我想:

bool myGet (context_t * someContext) {
    return (someContext->flag) ? (someContext->flag = false) : false;
}

推理(someContext->flag = false) 语句的评估结果将是true,但似乎不是。

也许它在条件(someContext->flag)? 之前进行了评估。

有没有其他方法可以实现预期的功能,而无需临时存储标志值、清除标志然后返回临时副本?谢谢。

【问题讨论】:

    标签: c return


    【解决方案1】:

    return 的所有参数必须在评估 return 本身之前评估,即在执行离开当前函数之前。

    赋值的值就是被赋值的值,所以你体验到的是false

    我认为最接近的是后增量,但这当然会严格限制可用的值。

    以明确的方式没有错

    bool getAndClear(context_t *someContext)
    {
      if(someContext->flag)
      {
        someContext->flag = false;
        return true;
      }
      return false;
    }
    

    它非常清晰,方式比你可怕的代码更容易理解。很容易想象编译器可以对其进行优化,因为它非常简单。

    如果我想变得聪明,我可能会使用类似的东西:

    bool getAndClear2(context_t *someContext)
    {
      const bool flag = someContext->flag;
    
      someContext->flag ^= flag; /* Clears if set, leaves alone if not set. */
    
      return flag;
    }
    

    请注意,它没有分支,这有时很漂亮。但是,再次强调,聪明并不总是最好的选择。

    还请注意,我认为此函数不只是命名为“get”某物的要求,因为它不需要 const 指针,这将是我脑海中的即时警告标志。由于它具有非常奇怪的(对于吸气剂)副作用,因此应该以某种方式反映在名称中。

    【讨论】:

    • 我喜欢这个不需要临时变量并且有相同数量的分支
    【解决方案2】:

    推理(someContext->flag = false) 语句的评估结果为真,但似乎不是。

    (someContext->flag = false) 是一个赋值表达式。它的值是被赋值的表达式的值(即false)。

    任务确实完成了,尽管它发生在返回之前,而不是之后。如果您想花哨并保留三元运算符,则可以使用逗号运算符,如下所示:

    return (someContext->flag) ? (someContext->flag = false, true) : false;
    

    不过,这不是很可读,所以我更喜欢这个等效的实现,它没有条件:

    bool temp = someContext->flag;
    someContext->flag = false;
    return temp;
    

    【讨论】:

      【解决方案3】:

      当您执行(someContext->flag = false) 时,它会将someContext->flag 设置为false,然后将其返回。

      你可以这样做:

      return (someContext->flag) ? !(someContext->flag = false) : false;
      

      这样您将返回您刚刚设置为 false 的 someContext->flag 的对立面(因此您返回 true),但 someContext->flag 在返回后将保持 false

      编辑

      最不可读的是:

      return !(someContext->flag = !someContext->flag);
      

      【讨论】:

      • 我喜欢这种方法,简短而甜蜜 :) 但是确实缺乏一些可读性,所以我可能不得不接受 unwind 的回答
      • 你习惯了就结束了,但我承认。它甚至可能是最坏的! (见编辑)
      【解决方案4】:

      你可以使用后减运算符:

      return (someContext->flag) ? someContext->flag-- : false;
      

      只有当您的标志的 true 值具有数值 1 时,这才会产生所需的结果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多