【问题标题】:Why does "int x = 5; printf("%d %d %d", x==5, x=10, x==5);" in C print "0 10 0"? [duplicate]为什么 "int x = 5; printf("%d %d %d", x==5, x=10, x==5);"在 C 中打印“0 10 0”? [复制]
【发布时间】:2019-09-28 20:57:17
【问题描述】:

我已经学习 C 大约一年了,我在上面玩的时候遇到了这个问题。我首先认为这可能是分配优先的情况(即 x=10 先发生),但后来我尝试了

printf("%d %d %d", x==5, x=10, x<6);

它输出 0 10 1。有人可以向我解释为什么/发生了什么,因为这对我来说似乎非常莫名其妙,我开始认为这可能是未定义的行为?

【问题讨论】:

  • 这是未定义的行为;任何结果都是可能的,并且与其他任何结果一样可以接受。
  • 为什么是未定义的行为,是不是因为我在 printf 中赋值?
  • 是的;未指定评估参数的顺序(甚至未定义实现),并且您尝试更改 x 的值以及在评估参数列表时在比较中使用该值,因此行为未定义.这是printf("%d %d %d\n", x--, x, ++x); 语句类型的一个微小变化——这也是未定义的行为,任何结果都是可以接受的。
  • @DavidC.Rankin: C11 §6.5.2.2 Function calls ¶10: 在函数指示符和实际参数的评估之后但在实际调用之前有一个序列点。调用函数(包括其他函数调用)中的每个求值,如果在被调用函数的主体执行之前或之后没有特别排序,则相对于被调用函数的执行是不确定的。94)。脚注 94 说:换句话说,函数执行不会相互“交错”。
  • 就是这个!

标签: c printf undefined-behavior


【解决方案1】:

这确实是未定义的行为。函数的参数以未指定的顺序进行评估,因此任何依赖于该顺序的操作都会变成 UB。

看起来你的编译器是从右到左的(至少在这种情况下)。这是一种合理的做法。不过既然是 UB,就别指望它总是那样做。

【讨论】:

  • 对未排序评估的依赖并不总是未定义的行为。
  • “未指定的顺序”不准确。这个答案应该说函数参数的评估是“无序的”。 C 有两种类型的不完全排序:未排序和不确定排序。在未排序的评估中,部分评估可以交错。在不确定排序的评估中,评估可以按任何顺序进行,但不能交错。导致副作用具有未定义行为的规则仅适用于未排序的评估。
  • @EricPostpischil 这是一个更好的答案;恐怕我对 UB 的了解没有那么深(我只知道“不要依赖函数操作数求值的顺序”)
  • 您无法区分未指定的行为未定义的行为
  • @MM:是的。例如,f1(f2(),f3()) 可以执行f2() 然后f3(),或者可以执行f3() 然后f2(),但是如果两个评估顺序都不会调用UB,则整个表达式也不会。跨度>
猜你喜欢
  • 2019-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
相关资源
最近更新 更多