首页 新闻 会员 周边 捐助

C语言诡异的printf函数

0
[已解决问题] 解决于 2013-06-07 16:34

为什么下面的这两条语句的输出结果是这样?
int i=1;
printf("%d, %d, %d \n",i++,i++,++i);


为什么输出结果是3,2,4????????????????

沉没之鱼的主页 沉没之鱼 | 初学一级 | 园豆:188
提问于:2012-05-22 23:10
< >
分享
最佳答案
1

我的博客上有分析这类问题的文章。既然你问为什么结果是这个,我就不做试验了,根据经验分析下,但结论未必和你的实验结果相同,因为这种问题取决于编译器处理i++,++i中的++操作符方式和 push i 之间的顺序关系:不是printf诡异,而是你把++运算符放到参数列表上,对编译器来说这一定会引发“强烈”的歧义。由于没有明确规则,所以给出什么输出结果,取决于编译器了。

------------------------------------

int i=1;
printf("%d, %d, %d \n",i++,i++,++i);


为什么输出结果是3,2,4

---------------------------------

先扫描这条语句,可见有一条++i,这时候就 ++ 就地处理。所以 i = 2;

这时候 push 最右边的参数,所以栈里有了2.这是打印出来最右边数字。

接下来对中间的i++,编译器用temp=i; i++; push temp; 来处理,这时候压人了2. 这是中间那个数字。然后i变成了3.

接下来对最左边的i++,编译器用temp2=i; i++; push temp2; 这时候压入的就是3。然后i变成了4。

所以我认为c++编译器打印出来很可能是3,2,2(执行完毕时 i=4)。当然,这只是我没有实践的分析。具体取决于编译器的实现。

当然了,你说结果是3,2,4。那么只有一种可能,就是先处理完所有的++,然后把所有的push统一放到最后处理,就会形成这种结果:即这种顺序:

---------------------

++i; 右边的 (注意这时候如果不立即push)

----------------------

temp = i; 中间的 (2)

i++;

---------------------

temp2 = i; 左边的(3)

i++;

-------------------

push i            (4)

push temp     (2)

push temp2  (3)

--------------------

call printf ... 这时候打出来就是3,2,4.

所以如果出现了你问题中的结果,结论就是编译器把“push参数的操作”统一放到了“处理表达式中的++(不论前置的还是后置的)”之后。

奖励园豆:5
hoodlum1980 | 小虾三级 |园豆:573 | 2012-06-07 16:01
其他回答(4)
0
木愚 | 园豆:20 (初学一级) | 2012-05-23 22:47
0

我用的VC++6.0,照楼主那样输出是2,2,2,但我的猜测应该是1,2,4,我也不理解。。。我把三个都输出都写成一样的i++,输出的结果就是3个1,没看到楼主的提问前我可以理解,现在又有疑问了。。。

打伞的鱼 | 园豆:174 (初学一级) | 2012-05-27 10:16

2,2,2或许可能,但1,2,4估计是不可能的。因为里面有一个前置++。这个一定会在push之前处理掉。所以打印的时候栈里的参数至少是2,不会比2小,不可能打印出1来的。

支持(0) 反对(0) hoodlum1980 | 园豆:573 (小虾三级) | 2012-06-07 16:03

2,2,2或许可能,但1,2,4估计是不可能的。因为里面有一个前置++。这个一定会在push之前处理掉。所以打印的时候栈里的参数至少是2,不会比2小,不可能打印出1来的。

如果是:

++i;

push i

temp = i;

temp2 = i;

i++;

push temp

i++;

push temp2

-----------

结果就会是2, 2, 2. 这个处理和我博客上的对vc6的分析是一致的,即vc6看到语句中有i++ 这样的运算符,就先用准备好的临时变量把i的当前值保存起来。所以不管有多少个 i++,只要都是后置的i++,VC6里打印出来结果都是一样的数字。

比如i= 1; printf("%d, ... %d", i++, i++, ....., i++);

vc6会打印出很多个1.

支持(0) 反对(0) hoodlum1980 | 园豆:573 (小虾三级) | 2012-06-07 16:09

@hoodlum1980: 噢,受教了

支持(0) 反对(0) 打伞的鱼 | 园豆:174 (初学一级) | 2012-06-07 18:09
0

跟编译器有关吧。最好不要写容易造成歧义和让人蛋疼的代码

romi | 园豆:206 (菜鸟二级) | 2012-05-29 10:18
0

有些操作c++是没有定义的, 看编译器是如何实现的, 但是你应该为这种代码感到羞愧

likebeta | 园豆:179 (初学一级) | 2012-08-29 10:02
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册