0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

帶參數(shù)宏定義易出現(xiàn)的隱藏bug和定義方式歸納

嵌入式那些事 ? 來源:嵌入式那些事 ? 2023-10-20 15:26 ? 次閱讀

宏定義尤其是帶參數(shù)的宏定義,特別容易出現(xiàn)一些隱藏問題,因?yàn)楹甓x在預(yù)處理階段是按照定義原封不動(dòng)的進(jìn)行展開,此時(shí)如果展開之后涉及到運(yùn)算符優(yōu)先級(jí)的問題,那么隱藏bug就此出現(xiàn)。

這里我先列舉一個(gè)簡(jiǎn)單的例子,然后歸納下帶參數(shù)宏定義對(duì)于括號(hào)使用的一些說明。

1.構(gòu)造帶有隱藏bug的宏定義

下面定義兩個(gè)帶參數(shù)宏,MUL_TWO是將兩個(gè)數(shù)進(jìn)行相乘,MUL_THREE是將三個(gè)數(shù)進(jìn)行相乘。

#defineMUL_TWO(val1,val2)(val1*val2)
#defineMUL_THREE(x,y,z)(MUL_TWO(x,y)*z)

比如我這里計(jì)算2 * 3 * 4的運(yùn)算結(jié)果,那么只需調(diào)用宏MUL_THREE(2, 3, 4)就可得到計(jì)算結(jié)果為:24,計(jì)算結(jié)果是正確的。但是如果將MUL_THREE(2, 3, 4)修改為MUL_THREE(1+1, 1+2, 1+3),此時(shí)的運(yùn)算結(jié)果又是多少呢,很簡(jiǎn)單,我們將這個(gè)宏進(jìn)行展開,展開的過程如下所示:

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)

然后我們計(jì)算下,得出結(jié)果是7,是不是計(jì)算錯(cuò)誤了。

2.改造上述宏定義

這里的宏定義還是比較簡(jiǎn)單的,并且大多數(shù)的小伙伴應(yīng)該都知道在定義帶參數(shù)的宏時(shí),參數(shù)需要使用括號(hào)括起來,那么我們改造下上述的宏,改造結(jié)果如下所示:

#defineMUL_TWO(val1,val2)((val1)*(val2))
#defineMUL_THREE(x,y,z)(MUL_TWO(x,y)*z)

此時(shí)再來對(duì)MUL_THREE(1+1, 1+2, 1+3)進(jìn)行展開,展開的過程如下所示:

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)

然后我們計(jì)算下,得出結(jié)果是9,計(jì)算結(jié)果還是有問題。仔細(xì)檢查下宏定義,原來是對(duì)MUL_THREE宏的z沒有用括號(hào)括起來,這個(gè)問題也是比較容易犯的,修改好之后的宏如下所示:

#defineMUL_TWO(val1,val2)((val1)*(val2))
#defineMUL_THREE(x,y,z)(MUL_TWO(x,y)*(z))

此時(shí)再來對(duì)MUL_THREE(1+1, 1+2, 1+3)進(jìn)行展開,展開的過程如下所示:

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))

此時(shí)的計(jì)算結(jié)果就是沒問題的了。

這里我再提個(gè)問題,為什么你在MUL_THREE宏中,只使用括號(hào)括起了z,為啥x和y你不同等對(duì)待,確實(shí)哈,如果對(duì)于不是很熟悉的小伙伴,可能看到我說的情況,會(huì)毫不猶豫的也對(duì)x和y進(jìn)行同樣的保護(hù);也有的小伙伴看到我說的這個(gè)情況可能腦子里面就暈了。

3.帶參數(shù)宏定義對(duì)于括號(hào)使用的一些說明

其實(shí)不對(duì)x和y做保護(hù)是有一個(gè)前提的,那就是你所定義的每一個(gè)宏定義都要確保對(duì)在當(dāng)前宏中使用到的參數(shù)用括號(hào)進(jìn)行保護(hù)。不知道各位明白我的意思不,不明白的話,看看我下面的總結(jié)吧。

帶參數(shù)宏定義,對(duì)于括號(hào)何時(shí)使用的總結(jié):

(1).帶參數(shù)宏定義,如果參數(shù)在當(dāng)前的宏中有進(jìn)行運(yùn)算,那么必須對(duì)該參數(shù)使用括號(hào)括起來(類似例子中MUL_THREE里面的z,MUL_TWO里面的val1和val2);

(2).帶參數(shù)宏定義,如果參數(shù)沒有在當(dāng)前的宏中有進(jìn)行運(yùn)算,而是直接當(dāng)成參數(shù)傳遞給其他的宏,那么該參數(shù)是不用使用括號(hào)進(jìn)行保護(hù)的(類似例子中MUL_THREE里面的x和y)。

對(duì)于上面的總結(jié)第(2)點(diǎn),能夠?qū)鬟f給其他宏的參數(shù)不進(jìn)行括號(hào)保護(hù)是因?yàn)榭偨Y(jié)的第(1)點(diǎn)已經(jīng)對(duì)宏做了一個(gè)規(guī)定,只要所有的宏定義都按照第(1)點(diǎn)進(jìn)行書寫,那么第(2)點(diǎn)自然也就不會(huì)出什么問題。







審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7581

    瀏覽量

    135552
  • Mul
    Mul
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    7946
  • 宏定義
    +關(guān)注

    關(guān)注

    0

    文章

    49

    瀏覽量

    8981

原文標(biāo)題:C語言-帶參數(shù)宏定義易出現(xiàn)的隱藏bug和定義方式歸納

文章出處:【微信號(hào):嵌入式那些事,微信公眾號(hào):嵌入式那些事】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    C語言定義使用技巧

    寫好C語言,漂亮的定義很重要,使用定義可以防止出錯(cuò),提高可移植性,可讀性,方便性等等。下面列舉一些成熟軟件中常用的
    發(fā)表于 07-29 09:35 ?1083次閱讀

    C語言定義與枚舉類型知識(shí)

    定義的標(biāo)識(shí)符不占內(nèi)存,只是一個(gè)臨時(shí)的符號(hào),預(yù)編譯后這個(gè)符號(hào)就不存在了。在簡(jiǎn)單的程序使用參數(shù)定義可完成函數(shù)調(diào)用的功能,又能減少系統(tǒng)開銷,
    發(fā)表于 10-11 17:34 ?1494次閱讀

    C語言中常用的定義

    寫好C語言,漂亮的定義很重要,使用定義可以防止出錯(cuò),提高可移植性,可讀性,方便性等等。下面列舉一些成熟軟件中常用的
    發(fā)表于 10-18 10:05 ?1617次閱讀

    請(qǐng)問FLASH 的定義是如何定義的?為什么?

    ,"ramfuncs");#pragma CODE_SECTION(OffsetISR,"ramfuncs");#endif但是這個(gè)FLASH 的定義不知在哪里進(jìn)行
    發(fā)表于 06-11 07:42

    C語言定義使用技巧

    寫好C語言,漂亮的定義很重要,使用定義可以防止出錯(cuò),提高可移植性,可讀性,方便性 等等。下面列舉一些成熟軟件中常用得
    發(fā)表于 11-13 12:04 ?36次下載

    內(nèi)聯(lián)函數(shù)和定義的區(qū)別介紹

    定義是C語言提供的三種預(yù)處理功能的其中一種,這三種預(yù)處理包括:定義、文件包含、條件編譯。定義
    發(fā)表于 12-15 15:33 ?2314次閱讀
    內(nèi)聯(lián)函數(shù)和<b class='flag-5'>宏</b><b class='flag-5'>定義</b>的區(qū)別介紹

    不帶參數(shù)定義是什么?不帶參數(shù)定義的資料介紹詳細(xì)過程概述

    c語言中有一個(gè)定義,其中有一類就是不帶參數(shù)定義。
    發(fā)表于 09-04 15:38 ?5次下載

    當(dāng)使用參數(shù)調(diào)用時(shí),會(huì)將參數(shù)替換為主體

    在大多數(shù)定義示例中,每次出現(xiàn)參數(shù)名稱都帶有括號(hào),并且另一對(duì)括號(hào)通常會(huì)包圍整個(gè)
    的頭像 發(fā)表于 11-16 16:41 ?2199次閱讀

    對(duì)于定義與重復(fù)定義的問題

    對(duì)于定義與重復(fù)定義的問題
    發(fā)表于 11-29 18:21 ?1次下載
    對(duì)于<b class='flag-5'>宏</b><b class='flag-5'>定義</b>與重復(fù)<b class='flag-5'>定義</b>的問題

    C語言定義--單片機(jī)中斷

    在單片機(jī)中斷中可以使用定義代替函數(shù),減小系統(tǒng)運(yùn)行時(shí)間。1.參數(shù)定義的優(yōu)點(diǎn):用
    發(fā)表于 01-13 12:52 ?6次下載
    C語言<b class='flag-5'>宏</b><b class='flag-5'>定義</b>--單片機(jī)中斷

    C語言中的定義

    #define命令是C語言中的一個(gè)定義命令,它用來將一個(gè)標(biāo)識(shí)符定義為一個(gè)字符串,該標(biāo)識(shí)符被稱為名,被定義的字符串稱為替換文本。命令有兩種
    的頭像 發(fā)表于 09-28 16:05 ?3346次閱讀
    C語言中的<b class='flag-5'>宏</b><b class='flag-5'>定義</b>

    C語言定義的使用原理

    使用STM32開發(fā)的朋友不知道是否有發(fā)現(xiàn)過這樣的一些定義?
    的頭像 發(fā)表于 02-01 14:36 ?1516次閱讀

    c語言定義可以嵌套嗎?

    某些代碼或表達(dá)式替換為指定的字符串,從而使程序更加靈活和可讀性更高。定義的語法形式為: #define 名(參數(shù)列表) 體 其中,
    的頭像 發(fā)表于 09-04 17:38 ?3021次閱讀

    c語言參數(shù)定義

    c語言參數(shù)定義? C語言定義是一種替換機(jī)制
    的頭像 發(fā)表于 09-04 17:45 ?2288次閱讀

    define定義

    define定義 以#號(hào)開頭的都是編譯預(yù)處理指令,它們不是C語言的成分,但是C程序離不開它們,#define用來定義一個(gè),程序在預(yù)處理階段將用define
    的頭像 發(fā)表于 11-24 15:35 ?712次閱讀