来源| 杰瑞IC验证(ID:Jerry_IC) |原创作者| Q哥
芯片验证不仅是一个良心活,也是一个细心活。做一个项目,写代码的时间,远远赶不上调试的时间。Q哥最抓狂的就是被一个菜鸟的错误耽误半天工夫。
今天就跟大家来聊一聊运算符的优先级问题,下面所有的错误都是Q哥曾经犯过的,说多了都是泪啊。。。
Q哥最开始写代码的时候,还是按照数学上从左到右的思维来运算,所以把a左移1位再加b,误写成了 xyz = a << 1 + b; 还特意加了空格想区分开来。
殊不知这样实际等效于 xyz = a << (1+b) ; 而且,加空格完全不能改变优先级,新手一定要明白这一点! 正确的写法应该是 xyz = (a << 1) + b;。
2.位运算(& | ^)和比较运算(== !=)
如果是if(a+b == c), 那么+的优先级高于==,所以等效于if((a+b) == c)。
但是Q哥在修改代码的时候,只是把+改成^,忘了加括号,变成if(a&b == c)。
由于&的优先级低于==,所以等效于if(a&(b==c)),与原本的期望不符,从而引入了bug。
3.分支运算符和算术运算
分支运算符?:是一个三目运算符,xyz = mode ? b : c ;等价于
if(mode)
xyz=b;
else
xyz = c;
使用?:这种写法简洁明了,老司机的最爱。
需要注意的是,分支运算的优先级是低于算术运算的。
比如:
xyz = a + mode ? b : c ; 实际等效于 xyz = (a+mode) ? b : c;
xyz = mode ? b : c + d; 实际等效于 xyz = mode ? b : (c + d);
在修改代码的时候,尤其要注意。
4.inside运算与逻辑非运算
SystemVerilog的inside运算可以表示变量被一个集合、数组、队列所包含,相当于数学上元素和集合的包含关系,如 a inside {[0:9]},或者 a inside my_queue (my_queue是一个队列)。
Q哥本来是想判断a不在[0:9]之内,于是写了if(!a inside {[0:9]}) 。
但是因为!运算优先级高于 inside,所以等效于 if((!a) inside {[0:9]}),事与愿违。正确的写法应该是if(! (a inside {[0:9]}) ) .
总结
表达式里面的运算符是有优先级的,不能想当然的按照从左到右的思维来进行运算和判断。
运算符优先级问题通过加括号是完全可以避免的,但是实际中往往因为嫌麻烦或者嫌括号加太多影响代码可读写就省略掉。
尤其在修改代码的时候,必须格外谨慎。比如上面第2个例子,本来if(a+b == c)不加括号是OK的,但是把+改成^的时候忽略了这一点,结果引入了bug。
——The End——