12 .运算符的优先级 C语言有32个关键字却有44个运算符!运算符之间有固定的优先级,虽然它们可以分成15类优先级,但如果让一个程序员完全记住这些运算符之间的优先级关系,怕是老手也是不容易的吧。如果你的程序只是语法错误,这类错误是最容易解决的,编译器就会帮你检测出来;如果是你自己的逻辑出现错误,那么根据运行结果仔细检查一下代码可能也不难发现;但若是你的逻辑正确却记错了运算符的优先级关系,导致程序运行结果和你设想的不同,这种错误就很难查出了,因为在你的潜意识里,已经把这种错误点当成理所当然不用关注的。 请看下面一句代码代表什么意思: *string ++;
由于*和++但是单目运算符,优先级相同,但结合方向却是自右向左,那么*string++应该就是*(string++),取出当前字符后将指针后移。不知道有没有人把它认为是(*string)++,即取指针string所指向的对象,然后将该对象增1. 我曾经在代码中不止一次的出现过因为优先级问题而导致的程序逻辑错误,那个时候我并没有完整的记过优先级,二十使用了一种“偷巧”的方法:只是简单记住前几级优先级,其它自己没把握的一律使用括号。这种方法我现在是不推荐的,一是因为大量的括号影响代码阅读和程序的简洁,二是总有时候我们稍微一松懈,就忘记了加括号,而后一种情况,正是很多人可能会遇到的。比如下面一句代码,无符号8位变量ucTimeValue 中存放十进制编码的数据23,我想将十进制编码转成16进制编码,代码为: temp8=(ucTimeValue>>4)*10+ucTimeValue&0x0F; //十进制转化为16进制,但忽略了运算符'+'的优先级是大于运算符'&'的
像这类代码编译肯定可以通过,但运行的结果却出乎我的意料,而且由于我先入为主的错误思想,要在一大段代码中发现这个错误着实要花费一番功夫。 再例如,如果我想判断一个寄存器的某一位是否为零,假如是判断寄存器IO0SET的bit17是否为零,但代码却写成了这样: if(IO0SET&(1<<17)==0)
这样写其实是得不到正确的结果的,因为我忽略了"=="的优先级是大于"&"的.按照上面的代码分析:因为"=="的优先级大于"&",所以程序先判断(1<<17)是否等于0?发现这是不相等的,所以(1<<17)==0表达式的值为假,即为0,0与(&)上任何一个数都是0,所以IO0SET&(1<<17))==0整个表达式的值永远为0,这与原意相差甚远。 按照原意,应该这样写:
if((IO0SET&(1<<17)))==0)
其实,运算符的优先级是有一定的规律可循的,下面给出优先级口诀(注:口诀来源于互联网)
优先级口诀 括号成员第一; 括号运算符[]() 成员运算符. -> 全体单目第二; 所有的单目运算符比如++ -- +(正) -(负) 指针运算*& 乘除余三,加减四; 这个"余"是指取余运算即% 移位五,关系六; 移位运算符:<< >> ,关系:> < >= <= 等 等于(与)不等排第七; 即== != 位与异或和位或; 这几个都是位运算: 位与(&)异或(^)位或(|) "三分天下"**十; 逻辑或跟与; 逻辑运算符:|| 和 && 十二和十一; 注意顺序:优先级(||) 底于 优先级(&&) 条件高于赋值, 三目运算符优先级排到 13 位只比赋值运算符和","高 逗号运算级最低! 逗号运算符优先级最低
|