宏定義尤其是帶參數(shù)的宏定義,特別容易出現(xiàn)一些隱藏問題,因為宏定義在預(yù)處理階段是按照定義原封不動的進行展開,此時如果展開之后涉及到運算符優(yōu)先級的問題,那么隱藏bug就此出現(xiàn)。
這里我先列舉一個簡單的例子,然后歸納下帶參數(shù)宏定義對于括號使用的一些說明。
1.構(gòu)造帶有隱藏bug的宏定義
下面定義兩個帶參數(shù)宏,MUL_TWO是將兩個數(shù)進行相乘,MUL_THREE是將三個數(shù)進行相乘。
#defineMUL_TWO(val1,val2)(val1*val2) #defineMUL_THREE(x,y,z)(MUL_TWO(x,y)*z)
比如我這里計算2 * 3 * 4的運算結(jié)果,那么只需調(diào)用宏MUL_THREE(2, 3, 4)就可得到計算結(jié)果為:24,計算結(jié)果是正確的。但是如果將MUL_THREE(2, 3, 4)修改為MUL_THREE(1+1, 1+2, 1+3),此時的運算結(jié)果又是多少呢,很簡單,我們將這個宏進行展開,展開的過程如下所示:
MUL_THREE(1+1,1+2,1+3)=>(MUL_TWO(1+1,1+2)*1+3) (MUL_TWO(1+1,1+2)*1+3)=>((1+1*1+2)*1+3)
然后我們計算下,得出結(jié)果是7,是不是計算錯誤了。
2.改造上述宏定義
這里的宏定義還是比較簡單的,并且大多數(shù)的小伙伴應(yīng)該都知道在定義帶參數(shù)的宏時,參數(shù)需要使用括號括起來,那么我們改造下上述的宏,改造結(jié)果如下所示:
#defineMUL_TWO(val1,val2)((val1)*(val2)) #defineMUL_THREE(x,y,z)(MUL_TWO(x,y)*z)
此時再來對MUL_THREE(1+1, 1+2, 1+3)進行展開,展開的過程如下所示:
MUL_THREE(1+1,1+2,1+3)=>(MUL_TWO(1+1,1+2)*1+3) (MUL_TWO(1+1,1+2)*1+3)=>(((1+1)*(1+2))*1+3)
然后我們計算下,得出結(jié)果是9,計算結(jié)果還是有問題。仔細檢查下宏定義,原來是對MUL_THREE宏的z沒有用括號括起來,這個問題也是比較容易犯的,修改好之后的宏如下所示:
#defineMUL_TWO(val1,val2)((val1)*(val2)) #defineMUL_THREE(x,y,z)(MUL_TWO(x,y)*(z))
此時再來對MUL_THREE(1+1, 1+2, 1+3)進行展開,展開的過程如下所示:
MUL_THREE(1+1,1+2,1+3)=>(MUL_TWO(1+1,1+2)*(1+3)) (MUL_TWO(1+1,1+2)*(1+3))=>(((1+1)*(1+2))*(1+3))
此時的計算結(jié)果就是沒問題的了。
這里我再提個問題,為什么你在MUL_THREE宏中,只使用括號括起了z,為啥x和y你不同等對待,確實哈,如果對于不是很熟悉的小伙伴,可能看到我說的情況,會毫不猶豫的也對x和y進行同樣的保護;也有的小伙伴看到我說的這個情況可能腦子里面就暈了。
3.帶參數(shù)宏定義對于括號使用的一些說明
其實不對x和y做保護是有一個前提的,那就是你所定義的每一個宏定義都要確保對在當前宏中使用到的參數(shù)用括號進行保護。不知道各位明白我的意思不,不明白的話,看看我下面的總結(jié)吧。
帶參數(shù)宏定義,對于括號何時使用的總結(jié):
(1).帶參數(shù)宏定義,如果參數(shù)在當前的宏中有進行運算,那么必須對該參數(shù)使用括號括起來(類似例子中MUL_THREE里面的z,MUL_TWO里面的val1和val2);
(2).帶參數(shù)宏定義,如果參數(shù)沒有在當前的宏中有進行運算,而是直接當成參數(shù)傳遞給其他的宏,那么該參數(shù)是不用使用括號進行保護的(類似例子中MUL_THREE里面的x和y)。
對于上面的總結(jié)第(2)點,能夠?qū)鬟f給其他宏的參數(shù)不進行括號保護是因為總結(jié)的第(1)點已經(jīng)對宏做了一個規(guī)定,只要所有的宏定義都按照第(1)點進行書寫,那么第(2)點自然也就不會出什么問題。
審核編輯:劉清
-
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136841 -
Mul
+關(guān)注
關(guān)注
0文章
5瀏覽量
7959 -
宏定義
+關(guān)注
關(guān)注
0文章
50瀏覽量
9013
原文標題:C語言-帶參數(shù)宏定義易出現(xiàn)的隱藏bug和定義方式歸納
文章出處:【微信號:嵌入式那些事,微信公眾號:嵌入式那些事】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論