【问题标题】:Confusion with Associativity of Assignment operator in C与 C 中赋值运算符的关联性混淆
【发布时间】:2011-08-05 10:02:55
【问题描述】:

众所周知,赋值运算符的结合性是从右到左,但是 在给定的代码中,如果我们从右到左,输出应该为零,但输出为 1。

 main()
 {
 int a=3,b=2;
 a=a==b==0;
 printf("%d",a);
 }

如果我们右转 letf,输出如何为 1??

如果我们从右到左,那么 (b==0) 应该首先被评估并给出结果 0,然后表达式 (a==0) 被评估也给出 0,最后 a 的值将是 0。

【问题讨论】:

  • 如果您不理解在同一语句中使用的比较运算符,理解赋值运算符并不能帮助您。
  • 谢谢Kerrek 我明白了
  • a == b == c 等同于 (a == b) == c ...
  • 这与 Xcode 无关。任何合理的 IDE(并且根本没有任何 IDE)中的任何符合标准的 C 编译器都会产生相同(正确)的结果。另外,不,不是,但请阅读有关 C 运算符的 Wikipedia 文章。
  • @H2CO3 想说的是它不是未定义,因此编译器不能做任何它想做的事情。它被评估为(equality_expression == equality_expression) == equality_expression,如规范中第 6.5.9 节中的状态,(以及 6.5.8 用于形成左侧部分的关系表达式)。我认为我的回答显示了一个简单的反例。

标签: c


【解决方案1】:

分配已完成 RTL,但相等 (==) 未完成。

语句实际上是:

a = ((a == b) == 0)

作业的右侧从左到右进行评估。在步骤中,这就是正在发生的事情:

  1. a == b0
  2. 0 == 01
  3. 1 分配给 a

【讨论】:

  • 我认为它与比较运算符的关联性有关,而不是其他方式。
  • @Amit:comparison 运算符从左到右!对于 assignment 运算符的一个很好的例子,你应该考虑a = b = c = 1;
【解决方案2】:

您的代码相当于:

a = ((a == b) == 0);

【讨论】:

    【解决方案3】:

    注意,这是从this question 合并而来的。 OP 询问为什么 a==b==c 等同于 Objective C 中的 a==b && b==c(这是 C 的严格超集)。我要求迁移此答案,因为它引用了此处其他答案未引用的规范。


    不,不是,就像(a==b) == c

    让我们看一个与您的规则相反的简单示例:

    (0 == 0 == 0);// evaluates to 0
    

    然而

    (0 == 0) && (0 == 0) // evaluates to 1
    

    逻辑有问题,因为:

    (0 == 0 == 0) 读出为 ((0 == 0) == 0),这与 1 == 0 相似,为 false (0)。


    对于有抱负的学生

    稍微深入了解如何评估。编程语言包括 grammar,它指定了您如何阅读该语言中的语句。 Siance Objective-C 没有实际的规范,我将使用 C 规范,因为 Objective-c 是 c 的严格超集。

    标准规定equality expression (6.5.9) 的评估如下:

    等式表达:

    关系表达式

    等式表达式 == 关系表达式

    等式表达式 != 关系表达式

    我们的情况是第二个,因为a == b == c 被读作equality_expression == relational_expression,其中第一个相等表达式是a == b

    (现在,实际结果数字与数字字面量有很大关系,equal->relational->shift->additive->multiplicative->cast->unary->postfix->primary->constant,但是这不是重点)

    所以规范明确指出a==b==c 确实评估与a==b && b==c 相同的方式

    值得一提的是,some languages 确实支持a<b<c 形式的表达式,但是,C 不是这样一种语言。

    【讨论】:

    • 值得一提的是,C 比较的结果是 int 而不是 BOOL
    • Xcode 评估 (1 == 1 == 1) 为真,但 (2 == 1 == 1) 为假。
    • @DanWesnor 对,因为 'truth' 的值为 1,而 'false' 的值为 0。所以 1 == 1 == 1 的计算结果为 (1 == 1) == 1,其计算结果为 1==1,其计算结果为 1,是真的。另一方面(2 == 1 == 1 评估为 (2 == 1) == 1)0 == 1 评估为 0 这是错误的。
    • @DanWesnor 去掉那个“Xcode”字。 Xcode 对您的代码没有任何作用,充其量只是将其传递给编译器。编译器中的 parser 传递是评估表达式的内容。现在去看看布尔值在 C 中是如何表示的,你就会明白为什么 1 == 1 == 1 是真的,1 == 1 == 1 == 1 也是如此。
    • @DanWesnor 值得一提的是,通常要提供像两个谓词(表达式)等价这样的逻辑声明,您必须证明它们对 所有 可能的输入产生相同的结果而不是针对特定分配(因此 1==1==1 并不表示 a==b==c a==b && b==c 以任何方式。
    猜你喜欢
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    相关资源
    最近更新 更多