1

为什么在比较操作完成后,下面的程序给了我相反的答案?

main()
{
    int k=35;
    printf("%d\n%d\n%d",k==35,k=50,k<40); 
}

输出

0 50 1

4

4 回答 4

9

根据 C 标准,该程序不是有效的 C 程序。
这个程序有两个问题。

问题 1:未指定的行为

函数参数的评估顺序是未指定的[参考 1]

  • 它可以从左到右或
  • 它可能是从右到左或
  • 任何其他魔法命令

问题 2:未定义的行为

这具有未定义的行为[Ref 2],因为在没有中间序列点的情况下,不应多次修改变量。请注意,,在函数参数中没有引入序列点。因此k在没有干预序列点的情况下被修改并导致未定义的行为。

因此,在这种情况下,您不能依赖行为是特定的。该程序不是有效的 C 程序。


[参考 1]
C99 标准 6.5.2.2.10:

函数指示符、实际参数和实际参数中的子表达式的求值顺序未指定,但在实际调用之前有一个顺序点。

[参考 2]
C99 标准 6.5.2:

在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,只能访问先验值以确定要存储的值。


请注意,未指定和未定义行为是标准定义的术语:

C99 标准 3.19 未指定行为:

本国际标准提供两种或多种可能性并且在任何情况下都没有强加任何要求的行为

C99 标准 3.18 未定义行为:

使用不可移植或错误程序构造、错误数据或不确定值对象时的行为,本国际标准对此没有要求

于 2013-05-26T07:47:04.040 回答
4

您是否注意到 printf 的第二个参数是 k=50?这是未定义的行为,因为未指定参数的评估顺序

于 2013-05-26T07:48:10.267 回答
4

C 标准没有定义函数参数的求值顺序。见 C99 §6.5.2.2p10

函数指示符、实际参数和实际参数中的子表达式的求值顺序未指定,但在实际调用之前有一个顺序点。

这意味着比较k==35、分配k=50和测试中的每一个k<40都可以以任何顺序发生。当我使用 MSVC 尝试您的程序时,首先发生了分配。其他编译器,甚至同一编译器的其他调用,可能会选择不同的顺序。

于 2013-05-26T07:48:29.207 回答
2

我希望你能展示你的输出。但是,我怀疑问题在于您已将赋值作为 printf() 的参数之一,并且天知道这三个参数的评估顺序是什么,即当 k==35 时 k 可能是 50评估;-)

于 2013-05-26T07:48:33.207 回答