一个容易犯错的运算优先级问题
2012年01月12日 分类目录 :程序语言 0
由于工作需要,在接受过系统Java培训的情况下,现在又开始学习起了C语言。虽说语言有着其共通的地方,但也会有着各式各样的差异,因此,在学习的过程中转变前一种语言的固有思维以适应新语言的规范就成了重中之重,而这也是最难的部分。
今天在新人C语言研讨会(由于主讲非专业讲师,因此称之为授课有点对不住“教师”这个称号)上讨论到运算结合律的时候,有一个案例是自真、自减的优先级演示。这是一个很坑爹的表达式,但是我们都能较为轻松地得出结果:
#include <iostream.h>
int main(){
int i = 3;
cout<<(i++)+(i++)+(i++)<<endl;
}
之后,一位同学&同事提出了更为自虐的式子,即将i++改为++i,顿时全都傻眼。当在VS中编译运行后得到的结果和我们认为的答案完全不一样,即使是作为主讲的一资深编码师也没能弄清如何得出这样一个答案的。
int main(){
int i = 3;
cout<<(++i)+(++i)+(++i)<<endl;
}
先说一下这个式子的答案,它将输出的结果是16(不知道你能算出这个答案吗?)
好了,现在开始解构这个坑人的式子:
由于编译器在解析运算式(从整体来看,忽略内含运算符的优先级别)的时候一般是按照“自左向右”的顺序来的,所以在这个式子中,我们先计算第一个++i,由于++在前表示的是先自增,后使用,所以这里i就自增为4。
然后我们来看(++i)+(++i)部分,在运算优先级这个问题上,虽然我们无法完全记住所有的运算符优先情况,但是自增优先级高于加法是肯定能记住的,所以此时先跳过加法,计算第二个++i,又由于第一个++i已经将i自增为了4,所以再经过一次自增会使得i变成5。且由于同一块内存区域无法同时用来存储2个常量,所以后来的常量会覆盖前面的常量,于是这部分式子在算术上就变成了5+5=10。
然后再继续看这个式子,经过前面的运算,我们已经可以把整个式子演变成 10 +(++i)了,此时,同样利用自增优先级高于加法的规则先进行++i的计算,由于前面的自增行为将i自增到了5,所以此次自增之后就得到i=6了。
最后10 + 6 就是16了。
经过这番解构,我们会发现似乎它是很基本的运算优先级的问题,每一个学过程序语言(无论是哪种具体的语言),都应该对它很熟悉,甚至很熟练。但是,事实上并非如此,当我们真的面对这样的式子的时候,我们根本无法熟练的使用优先级来做出正确的答案。最近在CSDN上看到很多帖子,都是新人想了解如何速成的方法,包括我也是,在仅知道些皮毛(虽说接受Java培训已有1年了)的情况下,就很想入手写代码,做程序了。但是,事实上,对于做程序来说,我们完全只是三角猫功夫,很容易就能被打回原型。咱有“冰冻三尺非一日之寒”之说,西方有“罗马不是一天建成的”的说法;咱又有“千里之行,始于足下”之说,所以说,当我们连基础都没打扎实的情况下,就想超前上项目,那就是白日做梦。——以上一段为自我批评,给自己的警示之言,也愿各位共勉。

















