使用赋值作为条件表达式?

Posted

技术标签:

【中文标题】使用赋值作为条件表达式?【英文标题】:Using assignment as a condition expression? 【发布时间】:2011-10-12 01:15:12 【问题描述】:

考虑:

if (a=5) 
   /* do something */

作业如何作为条件起作用?

是不是基于l-value的非零值?

【问题讨论】:

你是用 C++ 还是 C 编译? int war = false; if(war = true) launchnuke(); @WTP:永远不要将布尔值与任何东西进行比较。布尔值已经是布尔值:if (war) launchnuke();truefalse 分配给非布尔值的程序员应该受到各种针对他们的攻击。 @David:WTP 在哪里比较布尔值和布尔值? @Tomalak:他没有,但if(var = true) 可能打算成为if(var == true)。首先将其写为if (var) 可以巧妙地避免潜在的=== 的混淆。 【参考方案1】:

在更现代的用法中,您有时可能会看到这种模式用于处理 optionals:

std::optional x = ...;
if (auto v = x) 
  // Block only executes if x contained a value, accessible as *v

【讨论】:

【参考方案2】:

C++ — ISO/IEC 14882:2003(E)

[5.17/1]有几个赋值操作符,都是分组的 右到左。都需要一个可修改的左值作为左操作数, 赋值表达式的类型是其左操作数的类型。 赋值操作的结果是左边存储的值 赋值后的操作数;结果是一个左值。

表达式a = 5 的结果是5

[6.4/4] [..] 作为表达式的 condition 的值是 表达式,隐式转换为bool switch。 [..]

发生到bool 的转换。

[4.12/1] 算术、枚举、指针或指向成员的指针的右值 type 可以转换为bool 类型的右值。零值,null 指针值,或者空成员指针值转换为false任何 其他值转换为true

5 转换为布尔值true

[6.4.1/1] 如果条件 (6.4) 第一个结果为真 子语句被执行。 [..]

true 被视为if 语句成功。


C — ISO/IEC 9899:1999(E)

[6.5.16/3] 赋值运算符将值存储在对象中 由左操作数指定。 赋值表达式具有值 赋值后的左操作数,但不是左值。 [..]

表达式a = 5 的结果是5

[6.8.4.1/2] 在这两种形式中,如果 表达式比较不等于 0。 [..]

5 被视为if 语句成功。


一般

这样的代码几乎总是错误的;作者可能打算if (a == 5) 。然而,有时它是故意的。你可能会看到这样的代码:

if (x = foo()) 
   cout << "I set x to the result of foo(), which is truthy";
   // ... stuff

【讨论】:

为了确保没有错,你可以写if ((a=5) != 0),它在语义上与if (a=5)相同。 0.0 会被视为零值吗? @Stan:在我看来为零! (虽然记得浮点是不准确的。) 由于该问题同时被标记为 C 和 C++,因此可能很高兴提及您引用的是 C++,而不是 C。两者的推理相当不同。 @Tomalak Geret'kal:字体可以小一点。【参考方案3】:

是的,它基于分配给 a 的零/非零值。对于某些人(包括我自己)来说,在代码中使用带有副作用的表达式也被认为是不好的做法,因此上述代码片段最好写成类似

a = 5;
...
if (a != 0) 
    ...

【讨论】:

我认为 if (int a=foo()) ... ... if-scoped assignment 没问题。【参考方案4】:

if(a=x) 等价于 if(x) 除了分配有xa。因此,如果表达式x 的计算结果为非零值,那么if(x) 将简单地变为if(true)。否则变为if(false)

在您的情况下,由于x = 5,这意味着f(a=5) 除了分配有5a 之外,还等同于if(true)

【讨论】:

这有点误导:if(a=5) 不等同于if(true),因为它也分配了a -1: if (a = x)' and if (x)' 不等价,第一个表达式有副作用。 @interjay:我刚刚编辑了这个,当时你们俩都在评论。【参考方案5】:

每个非零值都将被视为true

所以有些人会建议你写

5 == a

为了避免你犯==的错误=

【讨论】:

现在大多数编译器都会警告这个错误。 @Bo Persson:当然是这样。但是有些懒惰的人想关闭警告,所以让我们将其设为错误而不是警告。 -1:对我来说这是丑陋的,并没有提供通用的解决方案。 我不建议写5 == a。我建议写a == 5。 :) 去做就对了;这并不难。如果你关闭警告,那么你应该得到你所得到的一切。 @Tomalak Geret'kal:我同意你的看法。所以我说的是“一些人”,而不仅仅是“我”。当然 '5==a' 很丑陋,但是,有些人(例如我的老板)会协助...有时您必须投降。

以上是关于使用赋值作为条件表达式?的主要内容,如果未能解决你的问题,请参考以下文章

while 条件中的赋值表达式是一种不好的做法?

在 Visual Studio 2010 中防止条件表达式中的赋值

C语言中三目运算符是啥?

循环结构

Python之路,Day3

简化条件表达式