前言:
晶片驗證不僅是一個良心活,也是一個細心活。做一個項目,寫代碼的時間,遠遠趕不上調試的時間。Q哥最抓狂的就是被一個菜鳥的錯誤耽誤半天工夫。
今天就跟大家來聊一聊運算符的優先級問題,下面所有的錯誤都是Q哥曾經犯過的,說多了都是淚啊。。。
Q哥最開始寫代碼的時候,還是按照數學上從左到右的思維來運算,所以把a左移1位再加b,誤寫成了 xyz = a << 1 + b; 還特意加了空格想區分開來。
殊不知這樣實際等效於 xyz = a << (1+b) ; 而且,加空格完全不能改變優先級,新手一定要明白這一點! 正確的寫法應該是 xyz = (a << 1) + b;。
如果是if(a+b == c), 那麼+的優先級高於==,所以等效於if((a+b) == c)。
但是Q哥在修改代碼的時候,只是把+改成^,忘了加括號,變成if(a&b == c)。
由於&的優先級低於==,所以等效於if(a&(b==c)),與原本的期望不符,從而引入了bug。
分支運算符?:是一個三目運算符,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);
在修改代碼的時候,尤其要注意。
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。
來源| 傑瑞IC驗證(ID:Jerry_IC)
往期回顧:
驗證工程師經常犯的錯誤(1)