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

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

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

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

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

宏定義尤其是帶參數(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)點自然也就不會出什么問題。







審核編輯:劉清

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

    關(guān)注

    180

    文章

    7604

    瀏覽量

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

    關(guān)注

    0

    文章

    5

    瀏覽量

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

    關(guān)注

    0

    文章

    50

    瀏覽量

    9013

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

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

收藏 人收藏

    評論

    相關(guān)推薦

    C語言定義使用技巧

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

    C語言定義與枚舉類型知識

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

    C語言中常用的定義

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

    詳細聊聊container_of這個定義

    大家周末好,我是bug菌~ 今天主要是跟大家詳細聊聊container_of這個定義,非常經(jīng)典的,只是一直沒有抽時間細細品味,今天就跟大家一起來看看有何神奇之處。
    的頭像 發(fā)表于 11-13 09:45 ?698次閱讀

    請問FLASH 的定義是如何定義的?為什么?

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

    C語言定義使用技巧

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

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

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

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

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

    當使用參數(shù)調(diào)用時,會將參數(shù)替換為主體

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

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

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

    C語言定義--單片機中斷

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

    C語言中的定義

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

    c語言定義可以嵌套嗎?

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

    c語言參數(shù)定義

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

    define定義

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