我已经经历了其他类似的问题,但试图了解我所面临的情况。
所以,这是我的两行C代码。
int i=0;
printf("%d %d %d %d %d",i++,i--,++i,--i,i);
以下是我从GCC和Turbo C编译器获得的输出。
输出:
-1 0 0 0 0
输出:
-1 0 0 -1 0
我尝试了单独使用预增量运算符的各种实验,并且两个编译器的工作方式类似,但是当我使用上面的printf
语句时,输出会有所不同。
我知道Turbo C是一个古老的编译器,现在已经过时和非标准,但仍无法知道上面的代码有什么问题。
答案 0 :(得分:8)
这是未定义的行为,您在没有序列点的情况下多次读取和修改i
。 (函数参数列表中的,
不是序列点,也没有定义函数参数的评估顺序。)
编译器可以在这种情况下输出任何想要的内容。不要那样做。
通过在[C] undefined behavior
搜索此网站,查找大量其他类似问题。这很有启发性。
答案 1 :(得分:1)
Turbo C正在将printf()
的参数从变量参数列表中的最后一个参数计算到第一个参数,并按此顺序打印(即,它填充最后一个值,然后继续前进最后一次评估的列表是列表中的第一个变量参数,它打印到格式化字符串中的第一个整数槽。另一方面,GCC首先评估具有预先修复运算符的参数,连接这些结果,并将它们应用于所有预修复运算符(即,它应用--i
和++i
结束up等于0
,然后将该值用于与这些参数关联的格式字符串中的两个槽。然后它转移到后修复操作符(第一个i--
然后是i++
),最后它评估变量args而没有预先修复或后修复操作符(即{{{ 1}},此时只是i
)。正如其他人所指出的那样,排序可以是任意的。
答案 2 :(得分:0)
无法保证评估功能参数的顺序;这是未定义的行为。
此订单可能会从版本更改为版本,甚至可以编译为编译。
答案 3 :(得分:0)
对于这种情况, Turbo C 编译器有一个具体的解释。
虽然 GCC 或其他现代编辑器对此类歧义持续存在未定义行为。
所以,这是 Turbo C 编译器的解释。
printf()在评估时具有从右到左的关联性,但会以从左到右的正常方式打印。
最初 i 的值初始化为 0 ,
从最右边的 i 开始,它将被 0 取代。
然后,第二个 - i 将替换为0-1 = -1 。
然后中间的一个 ++ i ,将被-1 + 1 = 0 取代。
然后第二个 i - ,将被 0 取代,但现在i的值变为-1。
然后第一个 i ++ ,将被 -1 取代,但现在i的值变为0.
最后以左到右的方式打印:
-1 0 0 -1 0
因此,您可以观察 Turbo C 编译器对此类表达式的通常行为,而此类表达式上没有任何其他编译器的具体规则。