【问题标题】:How the following c outputs garbage?以下c如何输出垃圾?
【发布时间】:2020-04-18 06:35:43
【问题描述】:
#include <stdio.h>

int main(void) {
   int d, a = 1 & 0 && (d=4);
   printf("%d\n", d);
   return 0;
}

根据操作符优先级() 语句d 应该被赋值但是在上面的程序中是逻辑的并且是最先执行的。 d 值未分配给 4。请任何人帮助我理解上述程序。我试过 gcc 和一些在线编译器

【问题讨论】:

标签: c operator-precedence


【解决方案1】:

我们先看f() + g() * h()

优先级和关联性定义了什么是什么的操作数。例如, C operator precedence and associativity 告诉我们

f() + g() * h()

意思

f() + ( g() * h() )     # * has higher precedence than +

而不是

( f() + g() ) * h()     # If + had higher precedence than *

值得注意的是,优先级不决定运算数的计算顺序。在我们的示例中,可以按任何顺序调用这三个函数,只要 g() 的结果和h() 的结果相乘,相乘的结果与f() 的结果相加。


返回

1 & 0 && ( d = 4 )

优先级和关联性只是告诉我们,上面等价于下面:

( 1 & 0 ) && ( d = 4 )    # & has higher precedence than &&

那么这有什么作用呢?

&amp;&amp; 规定仅在其左侧为真时才评估其右侧。这称为short-circuit evaluation 或短路。

1 &amp; 0 为假,因此永远不会评估 d = 4。这使d 保持不变,因此未初始化。

【讨论】:

  • 如果我将语句 iint 更改为 a = 1 || 1 & 0 && (d = 6) 然后它会变成 (1 || 1 & 0) && (d=6) 现在发生的事情 d 应该分配给 6。但是垃圾值再次存储在 d 中。跨度>
  • 不,它不会将 6 存储到 d。它再次打印垃圾值
  • int main() { int d;整数 a = 1 || 1 & 0 && (d = 6); printf("%d\n", a); printf("%d\n", d);返回0; }
  • testprint.c:6:24: 警告:“||”内的“&&” [-Wlogical-op-括号] int a = 1 || 1 & 0 && (d = 6); ~~ ~~~~~~^~~~~~~~~~ testprint.c:6:24: 注意:在 '&&' 表达式周围加上括号以消除此警告 int a = 1 || 1 & 0 && (d = 6); ^ ( ) 1 个警告生成。编译器消息没有错误
  • 1 || 1 &amp; 0 &amp;&amp; (d = 6) 不等同于(1 || 1 &amp; 0) &amp;&amp; (d=6),它等同于1 || ( ( 1 &amp; 0 ) &amp;&amp; (d = 6) ),并且我们已经确定( 1 &amp; 0 ) &amp;&amp; (d = 6) 不会评估&amp;&amp; 的RHS。
【解决方案2】:
  • 1 &amp; 0 &amp;&amp; (d=4) 的评估如下:(1 &amp; 0) &amp;&amp; (d=4)
  • (1 &amp; 0) 为 0
  • 因为short circuiting 右侧的&amp;&amp; 运算符未被计算
  • 因此永远不会评估d=4
  • 因此永远不会分配d
  • 因此d 包含垃圾,因为未初始化局部变量

如果您将int d 更改为int d = 42,您的程序的输出将为42

【讨论】: