(没有意义讨论)二元运算符和自加符的深入理解,小心多个++的陷阱
2013-04-11 13:21
155 查看
(文章使用gcc-4.6.2编译,本文不严谨的讨论了y=(++i)+(++i)+(++i)+(++i)表达式求值问题,其实这个讨论是没有意义的,原因参见:
/article/4776517.html)
最近看到了一道c语言题目,题目是这样的:
答案: x的值很容易看出来,是x=3+3=6,同时i=5。
y呢?在同一个运算表达式中两次++i后,是4+5还是5+5?正确答案是y=5+5=10,i=5。这里加法运算符左右两边都是变量x,所以5+5。
这个题目看似很简单,其实可以应发联想,若y的表达式为:
这时y的值是多少呢?y=7+7+7+7=28?
正确答案是y=23,i=7。为什么会出现这样的问题?
不理解这个问题,说明你对c语言运算符的运算规则还没有透彻的理解。
这里真实的运算规则是:
由于加法运算符“+”是二元运算符,所以每次运算都只需要2个操作数,运算后结果保存在一个缓存变量ans中。
所以先运算(++i)+(++i),则结果为ans=5+5=10,i=5;
然后再运算ans+(++i),则结果为ans=10+6=16,i=6;
然后再运算ans+(++i),则结果为ans=16+7=23,i=7;
然后赋值y=ans=23;
看到这里明白了吧,其实结合逆波兰表达式的堆栈求解方法很容易理解这个问题。
不要误以为y=(++i)+(++i)+(++i)+(++i)就是单纯运算4次自加后,i和i之间的加法。
同理思考问题:
是不是ans=3+3=6;ans=6+5=11;ans=11+6=17;y=17;?
你可以验证,发现y=3+3+3+3=12;
这说明这里的4个i++是在y的求职结束之后进行自加的。
这个问题怎么理解?和我们前面的结论有冲突?
其实没有冲突,真实的原因是你要理解i++和++i发生的准确条件:
对于++i,你完全可以用“(i=+1)”来替换,就是说,遇到++i一定是要先进行自加后才会完成其他的运算操作的。
对于i++,这里的自加,准确的讲,是整个逆波兰表达式操作数堆栈中所有的操作数全部清空后,才对需要自加的操作数自加的。简单的讲就是:忽略所有的i++操作符,先进行运算,等表达式的值求解完成后,才对相应的变量进行自加。
/article/4776517.html)
最近看到了一道c语言题目,题目是这样的:
int x,y,i=3; x=(i++)+(i++); i=3; y=(++i)+(++i); 问x和y的值分别是多少?
答案: x的值很容易看出来,是x=3+3=6,同时i=5。
y呢?在同一个运算表达式中两次++i后,是4+5还是5+5?正确答案是y=5+5=10,i=5。这里加法运算符左右两边都是变量x,所以5+5。
这个题目看似很简单,其实可以应发联想,若y的表达式为:
i=3; y=(++i)+(++i)+(++i)+(++i);
这时y的值是多少呢?y=7+7+7+7=28?
正确答案是y=23,i=7。为什么会出现这样的问题?
不理解这个问题,说明你对c语言运算符的运算规则还没有透彻的理解。
这里真实的运算规则是:
由于加法运算符“+”是二元运算符,所以每次运算都只需要2个操作数,运算后结果保存在一个缓存变量ans中。
所以先运算(++i)+(++i),则结果为ans=5+5=10,i=5;
然后再运算ans+(++i),则结果为ans=10+6=16,i=6;
然后再运算ans+(++i),则结果为ans=16+7=23,i=7;
然后赋值y=ans=23;
看到这里明白了吧,其实结合逆波兰表达式的堆栈求解方法很容易理解这个问题。
不要误以为y=(++i)+(++i)+(++i)+(++i)就是单纯运算4次自加后,i和i之间的加法。
同理思考问题:
i=3; y=(i++)+(i++)+(i++)+(i++)
是不是ans=3+3=6;ans=6+5=11;ans=11+6=17;y=17;?
你可以验证,发现y=3+3+3+3=12;
这说明这里的4个i++是在y的求职结束之后进行自加的。
这个问题怎么理解?和我们前面的结论有冲突?
其实没有冲突,真实的原因是你要理解i++和++i发生的准确条件:
对于++i,你完全可以用“(i=+1)”来替换,就是说,遇到++i一定是要先进行自加后才会完成其他的运算操作的。
对于i++,这里的自加,准确的讲,是整个逆波兰表达式操作数堆栈中所有的操作数全部清空后,才对需要自加的操作数自加的。简单的讲就是:忽略所有的i++操作符,先进行运算,等表达式的值求解完成后,才对相应的变量进行自加。
相关文章推荐
- 深入理解按位异或运算符
- 深入理解按位异或运算符
- 交换两个数不使用第三方变量=!!=深入理解按位异或运算符
- 深入理解JavaScript系列(6):根本没有“JSON对象”这回事!
- 深入理解JavaScript系列(9):根本没有“JSON对象”这回事!
- 交换两个数不使用第三方变量=!!=深入理解按位异或运算符
- (转)深入理解Linux操作系统守护进程的意义
- 深入理解Linux操作系统守护进程的意义
- C# 深入理解按位异或运算符^
- 深入理解JavaScript系列(9):根本没有“JSON对象”这回事!
- 深入理解按位异或运算符
- 深入理解Linux OS守护进程的意义
- 深入理解JavaScript系列(9):根本没有“JSON对象”这回事!
- 深入理解JavaScript系列(9) 根本没有“JSON对象”这回事!
- 深入理解JavaScript系列(9):根本没有“JSON对象”这回事!
- 深入理解Oracle索引(18):函数索引的陷阱以及如何避免索引被污染
- 转:[Java] 深入理解按位异或运算符
- ch01.深入理解C#委托及原理_《没有控件的ASPDONET》
- 深入理解virtual/new/override 这些关键字的意义
- 深入理解JavaScript系列 ----(9):根本没有“JSON对象”这回事!