这是我的简单代码......
#include<stdio.h>
int main()
{
int i=5;
printf("%d %d %d %d %d ",i++,i--,++i,--i,i);
return 0;
}
在gcc上,它输出为“4 5 5 5 5”
但在TC上,输出为“4 5 5 4 5”
我知道在printf语句中,如果是单个表达式,则评估将从左到右,但在正常语句中,它将从左到右。
但是如果printf包含多个表达式,那么评估将在堆栈上,元素将从左到右推入堆栈但从右到左弹出并证明TC输出是正确的
请纠正我在哪里错了???
答案 0 :(得分:8)
C没有指定应该评估哪些顺序函数参数,因此它是未定义的,编译器可以选择它,包括任意和随机。 Bjarne Stroustrup在“The C ++ Programming Language”第3版第6.2.2节中明确地说明了这一点
他也给出了一个理由:
Better code can be generated in the absence of restrictions on expression evaluation order
答案 1 :(得分:3)
我认为没有指定评估函数调用的参数的顺序。正如维基百科在关于序列点的this文章中所说:
未指定评估参数的顺序
答案 2 :(得分:3)
在前一个和下一个序列点之间多次修改一个对象(在此代码i
中)是C中未定义的行为。这里的序列点出现在所有参数被评估之后的函数调用中。
答案 3 :(得分:0)
此时的两个答案会调用函数参数评估的 unspecifiedness 。正确答案是您的程序未定义,因为对sequence point未分隔的同一变量产生副作用。
实际上,函数参数的评估顺序是未指定。这意味着在f(g(), h());
语句中,在g()
之前调用h()
或在之后调用它。
但是,未经测试的副作用(如在您的程序中)会调用未定义的行为,可能发生任何事情。
答案 4 :(得分:0)
提出一个旧主题,但我刚刚发现gcc和Visual Studio编译器如何处理语句中同一变量的多个更改,所以想在这里分享它。
这里定义的编译器开始对printf中传递的参数实现堆栈方法,即'i'。它遵循以下规则: -
1)现在它首先执行预增量,因此从右边正常开始然后--i然后执行++ i并且在++ i之后的i的值是5,所以它实现了这些值(pops)所以输出 _ _ 5 5 5
2)然后它从右到左继续并执行后增量因此,i--然后i ++因此i的值最终返回到5但由于i--它变为4但由于它显示5作为后增量,因此最终输出 4 5 5 5 5 ,i的最终值为5
希望我能清除你的怀疑。
TC不遵循这一点,因此它坚持我们的人类逻辑。