【问题标题】:Can we assign a value inside the if statement?我们可以在 if 语句中赋值吗?
【发布时间】:2019-07-23 15:31:02
【问题描述】:
#include <stdio.h>
void main()
{
    int x = 0;
    if (x = 0)
      printf("It's zero\n");
    else
      printf("It's not zero\n");
}

为什么声明 if (x = 0) 不是错误?我们可以在if 语句中分配这样的值吗?为什么它没有产生错误,为什么else 语句被执行?

【问题讨论】:

  • 你应该从你的编译器中得到一个警告,如果你没有,调高警告级别。
  • 是允许的,但是应该添加一组额外的括号来表明你真的想测试分配的结果。
  • 是的,可以在条件中赋值,在需要的时候非常有用,对于新手C程序员来说是个永远的陷阱。比较赋值结果0,看是否不等于0;它等于 0,所以if 为假,else 被执行。基本的 C 陷阱。并且该语句等效于:if ((x = 0) != 0) — 额外的括号向编译器说明您想要它。使用恒定的零,这是不明智的。使用可能为零的变量,这是有道理的,我更喜欢显式 != 0 作为表达式的一部分。 if ((x = 0)) 看起来很傻!
  • 面向表达式的编程语言允许更简洁的代码。他们不会强迫你separate commands from queries

标签: c if-statement variable-assignment


【解决方案1】:

是的,可以在if 语句中赋值。这非常方便,尤其是当您想要调用该函数并检查它是否返回错误时:

int rc;
if ((rc = check())) {
    // here rc is non-zero, often an indication of a failure
}

请注意我是如何在我的分配周围加上一对额外的括号 - 因为它是一个无所不在的混乱来源,编译器通常会警告 if 块中的分配,假设你可能打错了。额外的括号让编译器清楚地知道这是我的意图。

顺便说一句,这里没有特殊的例外,这种语法的有效性源于一般的 C 语法 - 赋值运算符评估为分配的值。

【讨论】:

  • 就我个人而言,我不喜欢这样的双括号口吃。我写if ((rc = check()) != 0)。它的意思相同——但更明确。
  • @JonathanLeffler 当然,我认为这是个人喜好问题。
  • @AndrewHenle 我不认为这个结构特别容易出错。如果您想根据其他条件(利用短路功能)的结果有选择地调用此函数,它会变得更加有趣。无论如何,YMMV 并没有人强迫你使用它。
  • @GovindParmar 我是 C++ 人,运算符对我来说是一个函数)))我认为,评估在 C 中更好。
  • @AndrewHenle 几乎没有争论。人们还倾向于从函数返回指向局部变量的指针并按值传递指针(并期望改变传递变量的值) - 这是禁止局部变量或按值传递的原因吗? C是一个复杂的工具,需要学习。无论如何,你有你的意见,我有我的意见。
【解决方案2】:

是的,这是一个完全有效的语法,没有理由禁止这样做。

引用C11

[...] 一个 赋值表达式具有赋值后左操作数的值。 [...]

因此,存储在 LHS 操作数中的值将用于if 语句条件评估。

在您的情况下,变量x 在赋值后保持值0,而if (0)FALSY,这就是else 块被执行的原因。


然而,大多数时候,这种语法被错误地使用,而不是比较。这就是为什么大多数编译器会在此构造上发出警告消息。

警告:建议在赋值周围使用括号作为真值 [-W括号]

 if (x = 0)
 ^

如果您确定自己在做什么,可以将 if 条件与赋值表达式括在另一对括号中,然后就可以开始了。

【讨论】:

    【解决方案3】:

    在 C 中,if 语句的唯一要求是它包含一个表达式。语句的真实性取决于表达式的计算结果是否为零。

    赋值运算符也计算分配的值,所以if(a = 0) 为假,而if(a = x) 其中x != 0 为真。

    由于赋值运算符是一个表达式,因此可以将其放在 if 语句中,尽管一个常见的初学者错误是在他们打算使用相等测试运算符 == 的地方使用赋值运算符。

    避免这种错误的一种方法是,如果比较的任一侧是 r 值,请将其放在左侧,这样如果您不小心使用了 =,而您的意思是 ==,您将得到一个编译错误。比较:

    if(p = NULL) // Valid syntax
        ...
    
    if(NULL = p) // Syntax error
        ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 2015-07-15
      • 2016-08-14
      相关资源
      最近更新 更多