色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

當使用參數調用宏時,會將參數替換為宏主體

Q4MP_gh_c472c21 ? 來源:技術讓夢想更偉大 ? 作者:李肖遙 ? 2020-11-16 16:41 ? 次閱讀

語法錯誤

當使用參數調用宏時,會將參數替換為宏主體,并與其他輸入文件一起檢查結果,以進行更多的宏調用,可以將部分來自宏主體和部分自變量的宏調用組合在一起。例如,

#definetwice(x)(2*(x)) #definecall_with_1(x)x(1) call_with_1(twice) //x=1 →twice(1) →(2*(1))

宏定義不必帶有括號,通過在宏主體中編寫不平衡的開放括號,可以創建一個從宏主體內部開始但在宏主體外部結束的宏調用。例如,

#definestrange(file)fprintf(file,"%s%d", … strange(stderr)p,35) →fprintf(stderr,"%s%d",p,35)

組合宏調用的功能可能會很有用,但是在宏主體中使用不平衡的開放括號只會造成混淆,應該避免。

運算符優先級問題

在大多數宏定義示例中,每次出現的宏參數名稱都帶有括號,并且另一對括號通常會包圍整個宏定義,這是編寫宏最好的方式。舉個例子

#defineceil_div(x,y)(x+y-1)/y

假定其用法如下:

a=ceil_div(b&c,sizeof(int));

拓展開是

a=(b&c+sizeof(int)-1)/sizeof(int);

這沒有達到我們的預期,C的運算符優先級規則使其等效于此,而我們想要的是:

a=(((b&c)+sizeof(int)-1))/sizeof(int);

如果我們將宏定義為

#defineceil_div(x,y)((x)+(y)-1)/(y)

可能導致另一種情況,sizeof ceil_div(1,2)是一個C表達式,可以計算ceil_div(1,2)類型的大小,它擴展為:

sizeof((1)+(2)-1)/(2)

這將采用整數的大小并將其除以2,而除法包含在內部的sizeof之外。所以整個宏定義的括號可防止此類問題。那么,下面是定義ceil_div的正確方法如下

#defineceil_div(x,y)((((x)+(y)-1)/(y))

吞噬分號

通常需要定義一個擴展為復合語句的宏。例如,考慮以下宏,該宏跨空格字符前進一個指針(參數p表示在何處查找):

#defineSKIP_SPACES(p,limit) {char*lim=(limit); while(p

該宏定義必須是單個邏輯行,嚴格來說,該調用擴展為復合語句,這是一個完整的語句,不需要用分號結束。

但是,由于它看起來像函數調用,因此,如果可以像使用函數調用一樣使用它,則可以最大程度地減少混亂,然后再寫一個分號,就像在SKIP_SPACES(p,lim)中一樣。

這可能會在else語句之前出問題,因為分號實際上是空語句。假設你寫

if(*p!=0) SKIP_SPACES(p,lim); else…

在if條件和else條件之間存在兩個語句(復合語句和null語句)使C代碼無效。

怎么解決?我們可以使用do…while語句更改宏SKIP_SPACES的定義以解決此問題。方法如下:

#defineSKIP_SPACES(p,limit) do{char*lim=(limit); while(p

SKIP_SPACES (p, lim);擴展為

do{…}while(0);

這是一個陳述,循環僅執行一次,而且大多數編譯器不會為此生成任何額外的代碼。

重復調用

我們常見的“最小”定義一個宏min,如下所示:

#definemin(X,Y)((X)

當將此宏與包含副作用的參數一起使用時,如此處所示,

next=min(x+y,foo(z));

它擴展如下:

next=((x+y)

其中x + y替換了X,而foo(z)替換了Y。

函數foo出現在程序中的語句中僅使用一次,但是表達式foo(z)已兩次替換到宏擴展中。結果,執行該語句時可能會兩次調用foo,所以min是一個不安全的宏。

解決此問題的最佳方法是以僅計算一次foo(z)值的方式定義min。C語言沒有提供執行此操作的標準方法,但是可以使用GNU擴展來完成此操作,如下所示:

#definemin(X,Y) ({typeof(X)x_=(X); typeof(Y)y_=(Y); (x_

“({{…})”符號產生一個復合表達式,它的值是其最后一條語句的值。

如果不使用GNU C擴展,唯一的解決方案是在使用宏min時要小心。例如計算foo(z)的值時,將其保存在變量中,然后在min中使用該變量:

//假設foo返回int類型 #definemin(X,Y)((X)

自引用宏

自引用宏是其名稱出現在其定義中的宏。我們知道所有宏定義都將被重新掃描以查找更多要替換的宏,如果自引用被認為是宏的使用,它將產生無限大的擴展。

為防止這種情況,自引用不被視為宏調用。它原樣傳遞到預處理器輸出中。舉個例子

#definefoo(4+foo)

按照普通規則,其宏定義分析如下

對foo的每個引用都將擴展為(4 + foo);

然后將對其進行重新掃描,并將其擴展為(4 +(4 + foo));

以此類推,直到計算機內存耗盡。

自引用規則將這一過程縮短了一步,即(4 + foo),因此此宏定義可能會導致程序在引用foo的任何地方將foo的值加4。

閱讀程序的人看到foo是變量,就難以記得它也是宏,真的會坑爹的。它的一種常見有用用法是創建一個可擴展為其自身的宏。如果你寫

#defineEPERMEPERM

然后宏EPERM擴展為EPERM。實際上,每當在運行文本中使用預處理器時,預處理器都會將其單獨保留。

如果宏x擴展為使用宏y,而y的擴展引用了宏x,則這是x的間接自引用。在這種情況下,x也不展開,舉個例子

#definex(4+y) #definey(2*x)

然后x和y擴展如下:

x→(4+y) →(4+(2*x)) y→(2*x) →(2*(4+y))

當每個宏出現在另一個宏的定義中時,它們將被展開,但是當它間接出現在其自己的定義中時,則不會被展開。

參數預掃描處理

宏參數在被替換為宏主體之前必須經過完全宏擴展,替換后,將再次掃描整個宏主體,包括替換的參數,以查找要擴展的宏。

如果參數包含任何宏調用,則它們將在第一次掃描時擴展,那么結果不包含任何宏調用,因此第二次掃描不會更改它。

如果按照給定的方式替換了參數,并且沒有進行預掃描,則剩余的單個掃描將找到相同的宏調用并產生相同的結果。

預掃描處理在以下三種特殊情況下有大的作用。

對宏的嵌套調用

當宏的參數包含對該宏的調用時,就會發生對宏的嵌套調用,舉個例子。

如果f是期望一個參數的宏,則f(f(1))是對f的嵌套調用對。通過擴展f(1)并將其代入f的定義來進行所需的擴展。預掃描會導致發生預期的結果。

如果沒有預掃描,f(1)本身將被替換為參數,并且f的內部使用將在主掃描期間作為間接自引用出現,并且不會擴展。

調用其他可進行字符串化或連接的宏的宏

如果參數是字符串化或串聯的,則不會進行預掃描。

如果要擴展宏,然后對其擴展進行字符串化或串聯,則可以通過使一個宏調用進行該字符串化或串聯的另一宏來實現。舉個例子

#defineAFTERX(x)X_##x #defineXAFTERX(x)AFTERX(x) #defineTABLESIZE1024 #defineBUFSIZETABLESIZE

然后AFTERX(BUFSIZE)擴展為X_BUFSIZE,而XAFTERX(BUFSIZE)擴展為X_1024而不是X_TABLESIZE,預掃描始終會進行完整的擴展。

參數中使用的宏,其擴展名包含未屏蔽的逗號。

這可能導致使用錯誤數量的參數調用在第二次掃描時擴展的宏。舉個例子

#definefooa,b #definebar(x)lose(x) #definelose(x)(1+(x))

我們預期的結果是bar(foo)變成(1 +(foo)),然后變成(1 +(a,b))。

然而bar(foo)擴展為loss(a,b)會出錯,因為Los需要一個參數。在這種情況下,該問題可以通過使用相同的括號輕松解決,該括號應用于防止算術運算的錯誤嵌套:

#definefoo(a,b) or #definebar(x)lose((x))

多余的一對括號可防止foo定義中的逗號被解釋為參數分隔符。

參數中的換行符

類似函數的宏的調用可以擴展到許多邏輯行,但是在本實施方式中,整個擴展是一行完成的。

因此,由編譯器或調試器發出的行號是指調用在其上開始的行,這可能與包含導致問題的參數的行不同,例如:

#defineignore_second_arg(a,b,c)a;c ignore_second_arg(foo(), ignored(), syntaxerror);

由Syntax error on tokens觸發的語法錯誤會導致錯誤消息引用第三行(ignore_second_arg行),即使有問題的代碼來自第五行。

責任編輯:lq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4803

    瀏覽量

    68750
  • 變量
    +關注

    關注

    0

    文章

    613

    瀏覽量

    28411
  • 語法
    +關注

    關注

    0

    文章

    44

    瀏覽量

    9838

原文標題:避免這7個誤區,才能讓【宏】削鐵如泥

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    常州市領導蒞臨微科技走訪調研

    近日,常州市市長周偉一行蒞臨江蘇微科技股份有限公司(以下簡稱微科技)新竹廠區走訪調研。
    的頭像 發表于 01-08 16:24 ?183次閱讀

    定義后面能不能加分號

    用define定義的,最后需不需要加分號?
    的頭像 發表于 01-06 16:35 ?116次閱讀

    景智駕總部落地衢州

    近日,景智駕衢州總部落地儀式在南孔圣地衢州東方橋庵里大酒店盛大舉行!衢州智造新城黨工委副書記、管委會常務副主任巫建民與景智駕創始人及CEO劉飛龍博士共同為落地儀式剪彩。
    的頭像 發表于 12-24 17:10 ?381次閱讀

    李彥宣布:百度文心大模型日調用量超15億

    在百度世界2024大會上,百度公司創始人李彥宣布了一項令人矚目的數據:百度文心大模型的日調用量已經超過15億次。這一數據不僅彰顯了百度在人工智能領域的領先地位,也預示著人工智能技術的廣泛應用
    的頭像 發表于 11-12 10:40 ?221次閱讀

    SV中define定義的用法

    SV中使用預處理指令`define來定義可以用來創建文本替換。根據場景不同,`define主要用來定義常量、簡化復雜的表達式或代碼段以及提高代碼的可移植性。其基本語法為:
    的頭像 發表于 10-21 14:22 ?654次閱讀

    科技與德賽電池簽約儲能電站合作項目

    科技和德賽電池儲能電站合作項目簽約儀式在勝科技隆重舉行。勝科技董事長陳濤、惠州德賽電池董事長曾劍云出席簽約儀式。勝科技CEO趙啟祥、惠州德賽電池總裁程月帆代表雙方簽約。
    的頭像 發表于 09-27 17:15 ?834次閱讀

    行業領導蒞臨景智駕考察交流

    近日,中國人才研究會汽車人才專業委員會理事長 朱明榮先生、同濟科技園常務副主任榮文偉先生一行蒞臨景智駕上海嘉定技術中心進行考察交流。 在深入了解景智駕公司發展情況后,各位領導對景智駕目前情況及未來發展給予了高度評價,并就
    的頭像 發表于 09-03 09:37 ?475次閱讀

    TINA仿真運放電路時,運放的參數中是否可以增加溫度參數呢?

    我們目前在使用TINA仿真運放電路的參數,從模型中找到了外圍電阻是有溫度參數可以設定的,包括線性溫度系數,二次溫度系數,指數溫度系數。但是運放本身的參數中目前沒有找到與溫度相關的參數
    發表于 08-14 07:31

    科技擬收購APCB 100%股權

    科技近期發布重要公告,宣布其計劃通過全資子公司新加坡勝及PSL,以不超過2.787億元人民幣的現金,全面收購APCB Electronics(Thailand)Co.,Ltd.(簡稱APCB)的100%股權。此次收購標志著勝
    的頭像 發表于 08-12 15:06 ?576次閱讀

    LF412用PSPICE驗證該運放的SPICE模型的遇到的疑問求解

    關于LF412,我用PSPICE驗證該運放的SPICE模型的遇到以下問題: 1.該模型缺少電壓噪聲和電流噪聲參數,有更加準確的SPICE模型嗎; 2.該模型開環輸出阻抗為純阻性
    發表于 08-06 06:16

    氣體成功斬獲無錫華潤上華電子大宗載氣項目,進軍存量市場

    此次中標被視為氣體領域重大突破,標志著成熟晶圓產線電子大宗載氣存量業務的替換成為可能,從而開拓金電子大宗載氣業務新的增長點。
    的頭像 發表于 04-19 15:27 ?444次閱讀

    證監會同意鑫科技創業板IPO注冊

    證監會發布關于同意浙江鑫科技股份有限公司首次公開發行股票注冊的批復,這標志著鑫科技在深交所創業板上市的腳步愈發臨近。作為國內較早開始應用鍛造工藝生產汽車鋁合金車輪的高新技術企業,鑫科技在行業內具有顯著的技術和市場優勢。
    的頭像 發表于 03-11 15:31 ?571次閱讀

    鑫科技即將掛牌上市

    浙江鑫科技股份有限公司(以下簡稱“鑫科技”)成功獲得證監會的批文,即將掛牌上市,這標志著鑫科技將成為資本市場鍛造鋁合金車輪第一股,迎來產業經營和資本運營雙輪驅動的全新發展階段。
    的頭像 發表于 03-11 15:30 ?797次閱讀

    CubeMx生成的stm32f013vet6設備,對于SDIOCLK頻率設置的定義與手冊里面對不上是為什么?

    在手冊里面有SDIO adapter clock (SDIOCLK = HCLK) HCLK設置為72MHz的時候進行配置SDIO_CK, 通過寄存器SDIO_CLKCR的位7:0(CLKDIV
    發表于 03-08 08:29

    如何利用Rust過程實現derive-with庫呢?

    通過派生 #[derive(With)] 給結構體字段生成 with_xxx 方法,通過鏈式調用 with_xxx 方法來構造結構體。
    的頭像 發表于 01-25 09:51 ?315次閱讀
    主站蜘蛛池模板: 怡春院欧美一区二区三区免费| 俄罗斯9一14 young处| 亚洲成年人影院| 在线欧美 精品 第1页| 国产线精品视频在线观看| 欧美无码专区| 坠落的丝袜美人妻| 精品午夜寂寞影院在线观看| 善良的女房东味道2在线观看| 2020年国产理论| 国内精品自线在拍2020不卡| 色综合久久久久久| 好爽胸大好深好多水| 亚洲 欧美 国产 综合 在线| 冠希和阿娇13分钟在线视频| 欧美影院在线观看完整版 mp4| 俄罗斯摘花| 亚洲欧美一区二区三区导航| 国产日韩成人内射视频| 视频一区二区中文字幕| 成人AV精品视频| 青青草国产偷拍在线av| a亚洲在线观看不卡高清| 麻豆国产精品va在线观看约| 中文字幕人妻无码系列第三区| 久久观看视频| 又紧又大又爽精品一区二区 | 灰原哀被啪漫画禁漫| 亚洲 日韩 在线 国产 视频| 久拍国产在线观看| 999视频精品全部免费观看| 美艳人妻在厨房翘着屁股| 99久久精品国内| 青青草原伊人网| 精品一成人岛国片在线观看| 抽插H浊水H嫩B父皇| 午夜插插插| 国产亚洲精品网站在线视频| 亚洲午夜精品AV无码少妇| 久久精品免费看网站| 97影院理论午夜伦不卡偷|