我在True和False之间感到困惑。真值是否代表零,虚值代表零?

时间:2013-05-26 07:44:03

标签: c

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

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

输出

0 50 1

4 个答案:

答案 0 :(得分:8)

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

问题1:未指明的行为

对函数参数的求值顺序为未指定 [Ref 1]

  • 可以从左到右或
  • 可能是向右或向
  • 任何其他神奇的命令

问题2:未定义的行为

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

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


[参考1]
C99标准6.5.2.2.10:

  

函数指示符的评估顺序,实际参数和   实际参数中的子表达式未指定,但有一个序列点   在实际通话之前。

[参考2]
C99标准6.5.2:

  

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


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

C99标准3.19未指明的行为:

  

此国际标准提供两种或更多种可能性的行为   在任何情况下都没有要求选择

C99标准3.18未定义的行为:

  

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

答案 1 :(得分:5)

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

答案 2 :(得分:4)

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

  

功能指示符的评估顺序,实际   参数和实际参数中的子表达式是   未指定,但在实际调用之前有一个序列点。

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

答案 3 :(得分:2)

我希望你能展示你的输出。但是,我怀疑问题在于你已经将一个赋值作为printf()的一个参数包含在内,而天堂知道三个参数的评估顺序,即当k == 35时,k可能是50。评估;-)