为什么下面的程序在比较操作完成后给出了相反的答案?
main()
{
int k=35;
printf("%d\n%d\n%d",k==35,k=50,k<40);
}
输出
0 50 1
答案 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。评估;-)