在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

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

工程師避免這些誤區(qū)才能讓【宏】削鐵如泥

工程師 ? 來(lái)源:嵌入式資訊精選 ? 作者:嵌入式資訊精選 ? 2020-10-23 15:15 ? 次閱讀

語(yǔ)法錯(cuò)誤當(dāng)使用參數(shù)調(diào)用宏時(shí),會(huì)將參數(shù)替換為宏主體,并與其他輸入文件一起檢查結(jié)果,以進(jìn)行更多的宏調(diào)用,可以將部分來(lái)自宏主體和部分自變量的宏調(diào)用組合在一起。例如,

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

宏定義不必帶有括號(hào),通過(guò)在宏主體中編寫(xiě)不平衡的開(kāi)放括號(hào),可以創(chuàng)建一個(gè)從宏主體內(nèi)部開(kāi)始但在宏主體外部結(jié)束的宏調(diào)用。例如,

#define strange(file) fprintf (file, “%s %d”,…strange(stderr) p, 35) → fprintf (stderr, “%s %d”, p, 35)

組合宏調(diào)用的功能可能會(huì)很有用,但是在宏主體中使用不平衡的開(kāi)放括號(hào)只會(huì)造成混淆,應(yīng)該避免。

運(yùn)算符優(yōu)先級(jí)問(wèn)題在大多數(shù)宏定義示例中,每次出現(xiàn)的宏參數(shù)名稱(chēng)都帶有括號(hào),并且另一對(duì)括號(hào)通常會(huì)包圍整個(gè)宏定義,這是編寫(xiě)宏最好的方式。舉個(gè)例子

#define ceil_div(x, y) (x + y - 1) / y

假定其用法如下:

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

拓展開(kāi)是

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

這沒(méi)有達(dá)到我們的預(yù)期,C的運(yùn)算符優(yōu)先級(jí)規(guī)則使其等效于此,而我們想要的是:

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

如果我們將宏定義為

#define ceil_div(x,y)((x)+(y)-1)/(y)

可能導(dǎo)致另一種情況,sizeof ceil_div(1,2)是一個(gè)C表達(dá)式,可以計(jì)算ceil_div(1,2)類(lèi)型的大小,它擴(kuò)展為:

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

這將采用整數(shù)的大小并將其除以2,而除法包含在內(nèi)部的sizeof之外。所以整個(gè)宏定義的括號(hào)可防止此類(lèi)問(wèn)題。那么,下面是定義ceil_div的正確方法如下

#define ceil_div(x,y)((((x)+(y)-1)/(y))

吞噬分號(hào)通常需要定義一個(gè)擴(kuò)展為復(fù)合語(yǔ)句的宏。例如,考慮以下宏,該宏跨空格字符前進(jìn)一個(gè)指針(參數(shù)p表示在何處查找):

#define SKIP_SPACES(p, limit) \{ char *lim = (limit); \ while (p 《 lim) { \ if (*p++ != ‘ ’) { \ p--; break; }}}

該宏定義必須是單個(gè)邏輯行,嚴(yán)格來(lái)說(shuō),該調(diào)用擴(kuò)展為復(fù)合語(yǔ)句,這是一個(gè)完整的語(yǔ)句,不需要用分號(hào)結(jié)束。

但是,由于它看起來(lái)像函數(shù)調(diào)用,因此,如果可以像使用函數(shù)調(diào)用一樣使用它,則可以最大程度地減少混亂,然后再寫(xiě)一個(gè)分號(hào),就像在SKIP_SPACES(p,lim)中一樣。

這可能會(huì)在else語(yǔ)句之前出問(wèn)題,因?yàn)榉痔?hào)實(shí)際上是空語(yǔ)句。假設(shè)你寫(xiě)

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

在if條件和else條件之間存在兩個(gè)語(yǔ)句(復(fù)合語(yǔ)句和null語(yǔ)句)使C代碼無(wú)效。

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

#define SKIP_SPACES(p, limit) \do { char *lim = (limit); \ while (p 《 lim) { \ if (*p++ != ‘ ’) { \ p--; break; }}} \while (0)

SKIP_SPACES (p, lim);擴(kuò)展為

do {…} while (0);

這是一個(gè)陳述,循環(huán)僅執(zhí)行一次,而且大多數(shù)編譯器不會(huì)為此生成任何額外的代碼。

重復(fù)調(diào)用我們常見(jiàn)的“最小”定義一個(gè)宏min,如下所示:

#define min(X, Y) ((X) 《 (Y) ? (X) : (Y))

當(dāng)將此宏與包含副作用的參數(shù)一起使用時(shí),如此處所示,

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

它擴(kuò)展如下:

next = ((x + y) 《 (foo (z)) ? (x + y) : (foo (z)));

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

函數(shù)foo出現(xiàn)在程序中的語(yǔ)句中僅使用一次,但是表達(dá)式foo(z)已兩次替換到宏擴(kuò)展中。結(jié)果,執(zhí)行該語(yǔ)句時(shí)可能會(huì)兩次調(diào)用foo,所以min是一個(gè)不安全的宏。

解決此問(wèn)題的最佳方法是以?xún)H計(jì)算一次foo(z)值的方式定義min。C語(yǔ)言沒(méi)有提供執(zhí)行此操作的標(biāo)準(zhǔn)方法,但是可以使用GNU擴(kuò)展來(lái)完成此操作,如下所示:

#define min(X, Y) \({ typeof (X) x_ = (X); \ typeof (Y) y_ = (Y); \ (x_ 《 y_) ? x_ : y_; })

“({{…})”符號(hào)產(chǎn)生一個(gè)復(fù)合表達(dá)式,它的值是其最后一條語(yǔ)句的值。

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

//假設(shè)foo返回int類(lèi)型#define min(X, Y) ((X) 《 (Y) ? (X) : (Y))…{ int tem = foo (z); next = min (x + y, tem);}

自引用宏自引用宏是其名稱(chēng)出現(xiàn)在其定義中的宏。我們知道所有宏定義都將被重新掃描以查找更多要替換的宏,如果自引用被認(rèn)為是宏的使用,它將產(chǎn)生無(wú)限大的擴(kuò)展。

為防止這種情況,自引用不被視為宏調(diào)用。它原樣傳遞到預(yù)處理器輸出中。舉個(gè)例子

#define foo (4 + foo)

按照普通規(guī)則,其宏定義分析如下

對(duì)foo的每個(gè)引用都將擴(kuò)展為(4 + foo);

然后將對(duì)其進(jìn)行重新掃描,并將其擴(kuò)展為(4 +(4 + foo));

以此類(lèi)推,直到計(jì)算機(jī)內(nèi)存耗盡。

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

閱讀程序的人看到foo是變量,就難以記得它也是宏,真的會(huì)坑爹的。它的一種常見(jiàn)有用用法是創(chuàng)建一個(gè)可擴(kuò)展為其自身的宏。如果你寫(xiě)

#define EPERM EPERM

然后宏EPERM擴(kuò)展為EPERM。實(shí)際上,每當(dāng)在運(yùn)行文本中使用預(yù)處理器時(shí),預(yù)處理器都會(huì)將其單獨(dú)保留。

如果宏x擴(kuò)展為使用宏y,而y的擴(kuò)展引用了宏x,則這是x的間接自引用。在這種情況下,x也不展開(kāi),舉個(gè)例子

#define x (4 + y)#define y (2 * x)

然后x和y擴(kuò)展如下:

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

當(dāng)每個(gè)宏出現(xiàn)在另一個(gè)宏的定義中時(shí),它們將被展開(kāi),但是當(dāng)它間接出現(xiàn)在其自己的定義中時(shí),則不會(huì)被展開(kāi)。

參數(shù)預(yù)掃描處理宏參數(shù)在被替換為宏主體之前必須經(jīng)過(guò)完全宏擴(kuò)展,替換后,將再次掃描整個(gè)宏主體,包括替換的參數(shù),以查找要擴(kuò)展的宏。

如果參數(shù)包含任何宏調(diào)用,則它們將在第一次掃描時(shí)擴(kuò)展,那么結(jié)果不包含任何宏調(diào)用,因此第二次掃描不會(huì)更改它。

如果按照給定的方式替換了參數(shù),并且沒(méi)有進(jìn)行預(yù)掃描,則剩余的單個(gè)掃描將找到相同的宏調(diào)用并產(chǎn)生相同的結(jié)果。

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

對(duì)宏的嵌套調(diào)用當(dāng)宏的參數(shù)包含對(duì)該宏的調(diào)用時(shí),就會(huì)發(fā)生對(duì)宏的嵌套調(diào)用,舉個(gè)例子。

如果f是期望一個(gè)參數(shù)的宏,則f(f(1))是對(duì)f的嵌套調(diào)用對(duì)。通過(guò)擴(kuò)展f(1)并將其代入f的定義來(lái)進(jìn)行所需的擴(kuò)展。預(yù)掃描會(huì)導(dǎo)致發(fā)生預(yù)期的結(jié)果。

如果沒(méi)有預(yù)掃描,f(1)本身將被替換為參數(shù),并且f的內(nèi)部使用將在主掃描期間作為間接自引用出現(xiàn),并且不會(huì)擴(kuò)展。

調(diào)用其他可進(jìn)行字符串化或連接的宏的宏如果參數(shù)是字符串化或串聯(lián)的,則不會(huì)進(jìn)行預(yù)掃描。

如果要擴(kuò)展宏,然后對(duì)其擴(kuò)展進(jìn)行字符串化或串聯(lián),則可以通過(guò)使一個(gè)宏調(diào)用進(jìn)行該字符串化或串聯(lián)的另一宏來(lái)實(shí)現(xiàn)。舉個(gè)例子

#define AFTERX(x) X_ ## x#define XAFTERX(x) AFTERX(x)#define TABLESIZE 1024#define BUFSIZE TABLESIZE

然后AFTERX(BUFSIZE)擴(kuò)展為X_BUFSIZE,而XAFTERX(BUFSIZE)擴(kuò)展為X_1024而不是X_TABLESIZE,預(yù)掃描始終會(huì)進(jìn)行完整的擴(kuò)展。

參數(shù)中使用的宏,其擴(kuò)展名包含未屏蔽的逗號(hào)。這可能導(dǎo)致使用錯(cuò)誤數(shù)量的參數(shù)調(diào)用在第二次掃描時(shí)擴(kuò)展的宏。舉個(gè)例子

#define foo a,b#define bar(x) lose(x)#define lose(x) (1 + (x))

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

然而bar(foo)擴(kuò)展為loss(a,b)會(huì)出錯(cuò),因?yàn)長(zhǎng)os需要一個(gè)參數(shù)。在這種情況下,該問(wèn)題可以通過(guò)使用相同的括號(hào)輕松解決,該括號(hào)應(yīng)用于防止算術(shù)運(yùn)算的錯(cuò)誤嵌套:

#define foo (a,b)or#define bar(x) lose((x))

多余的一對(duì)括號(hào)可防止foo定義中的逗號(hào)被解釋為參數(shù)分隔符。

參數(shù)中的換行符類(lèi)似函數(shù)的宏的調(diào)用可以擴(kuò)展到許多邏輯行,但是在本實(shí)施方式中,整個(gè)擴(kuò)展是一行完成的。

因此,由編譯器或調(diào)試器發(fā)出的行號(hào)是指調(diào)用在其上開(kāi)始的行,這可能與包含導(dǎo)致問(wèn)題的參數(shù)的行不同,例如:

#define ignore_second_arg(a,b,c) a; cignore_second_arg (foo (), ignored (), syntax error);

由Syntax error on tokens觸發(fā)的語(yǔ)法錯(cuò)誤會(huì)導(dǎo)致錯(cuò)誤消息引用第三行(ignore_second_arg行),即使有問(wèn)題的代碼來(lái)自第五行。

責(zé)任編輯:haq

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

    關(guān)注

    3

    文章

    4344

    瀏覽量

    62839
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1640

    瀏覽量

    49217
  • 宏匯編器
    +關(guān)注

    關(guān)注

    0

    文章

    7

    瀏覽量

    8995
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    工程師在電路設(shè)計(jì)中的八大誤區(qū)

    我們常常會(huì)發(fā)現(xiàn),自己想當(dāng)然的一些規(guī)則或道理往往會(huì)存在一些差錯(cuò)。電子工程師在電路設(shè)計(jì)中也會(huì)有這樣的例子。下面是一位工程師總結(jié)的八大誤區(qū)點(diǎn)。
    發(fā)表于 03-16 17:04 ?1625次閱讀

    電子工程師之路

    ,不應(yīng)該一直沉默寡言。假如你能正確的明白自己缺少什么條件,怎么去滿足這些條件,我想你基本就要成功了。本人不才,簡(jiǎn)單的說(shuō)下了。本人喜歡交工程師朋友。有愿意和哥們交朋友的還請(qǐng)留言。
    發(fā)表于 11-27 14:02

    工程師手記:FPGA學(xué)習(xí)的四大誤區(qū)

    工程師手記:FPGA學(xué)習(xí)的四大誤區(qū)
    發(fā)表于 08-17 23:47

    新手學(xué)習(xí)PADS的三個(gè)誤區(qū)

    很多新手經(jīng)常糾結(jié)的一件事就是學(xué)習(xí)PADS是不是可以拿高薪,是不是可以成為一個(gè)工程師,其實(shí)這些都是很大的誤區(qū),誤區(qū)大致都是在以下幾種情況第一:我很熟練的掌握了PADS工具,其實(shí)PADS與
    發(fā)表于 07-30 17:10

    如何才能讓自己成為一名嵌入式開(kāi)發(fā)工程師

    卻比比皆是。面對(duì)一個(gè)如此朝陽(yáng)的行業(yè),我們?nèi)绾?b class='flag-5'>才能讓自己成為一名嵌入式開(kāi)發(fā)工程師?成為一名優(yōu)秀的嵌入式開(kāi)發(fā)工程師有哪些要求?  我們都知道,嵌入式主要由硬件和軟件兩部分組成,硬件(微處理器硬件)是軟件
    發(fā)表于 11-08 07:40

    如何才能成為一個(gè)硬件工程師?

    如何才能成為一個(gè)硬件工程師
    發(fā)表于 11-11 07:11

    如何才能讓自己成為一名優(yōu)秀的嵌入式開(kāi)發(fā)工程師

      在互聯(lián)網(wǎng)行業(yè)中,嵌入式技術(shù)后來(lái)居上,因?yàn)槲锫?lián)網(wǎng)和人工智能的發(fā)展,嵌入式技術(shù)越來(lái)越值錢(qián),學(xué)嵌入式的人也越來(lái)越多。面對(duì)一個(gè)如此朝陽(yáng)的行業(yè),我們?nèi)绾?b class='flag-5'>才能讓自己成為一名優(yōu)秀的嵌入式開(kāi)發(fā)工程師?嵌入式入門(mén)
    發(fā)表于 12-17 06:46

    FPGA工程師需要具備哪些技能?

    ,需要具備一系列的技能,才能勝任日益復(fù)雜的設(shè)計(jì)工作。因此,本文將從設(shè)計(jì)思路、硬件語(yǔ)言、EDA工具、數(shù)字信號(hào)處理、通信協(xié)議、測(cè)試驗(yàn)證等多個(gè)方面,探討FPGA工程師需要具備哪些技能。 一
    發(fā)表于 11-09 11:03

    工程師故事:怎樣才能成為優(yōu)秀研發(fā)工程師呢?

    工程師故事:怎樣才能成為優(yōu)秀研發(fā)工程師呢?其實(shí)三言?xún)烧Z(yǔ)很難道盡工程師的成長(zhǎng)心得。多年的工作中,我們體會(huì)比較深刻的有以下幾個(gè)方面:
    發(fā)表于 03-22 16:17 ?4168次閱讀

    工程師在電路設(shè)計(jì)中的八大誤區(qū)

    工程師在電路設(shè)計(jì)中的八大誤區(qū),感興趣的小伙伴們可以瞧一瞧。
    發(fā)表于 05-12 10:28 ?0次下載

    什么樣的工程師才能被稱(chēng)為資深Java工程師

    什么樣的工程師才能被稱(chēng)為資深,又如何成為資深Java工程師呢?
    的頭像 發(fā)表于 08-05 16:15 ?3705次閱讀

    如何才能避免】的這七個(gè)誤區(qū)

    當(dāng)使用參數(shù)調(diào)用時(shí),會(huì)將參數(shù)替換為主體,并與其他輸入文件一起檢查結(jié)果,以進(jìn)行更多的調(diào)用,可以將部分來(lái)自主體和部分自變量的調(diào)用組合在一
    的頭像 發(fā)表于 12-24 14:29 ?423次閱讀

    電子工程師設(shè)計(jì)電路的十四誤區(qū)資料下載

    電子發(fā)燒友網(wǎng)為你提供電子工程師設(shè)計(jì)電路的十四誤區(qū)資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
    發(fā)表于 04-01 08:50 ?22次下載
    電子<b class='flag-5'>工程師</b>設(shè)計(jì)電路的十四<b class='flag-5'>誤區(qū)</b>資料下載

    一位工程師總結(jié)的電路設(shè)計(jì)八大誤區(qū)點(diǎn)資料下載

    電子發(fā)燒友網(wǎng)為你提供一位工程師總結(jié)的電路設(shè)計(jì)八大誤區(qū)點(diǎn)資料下載的電子資料下載,更有其他相關(guān)的電路圖、源代碼、課件教程、中文資料、英文資料、參考設(shè)計(jì)、用戶指南、解決方案等資料,希望可以幫助到廣大的電子工程師們。
    發(fā)表于 04-21 08:52 ?9次下載
    一位<b class='flag-5'>工程師</b>總結(jié)的電路設(shè)計(jì)八大<b class='flag-5'>誤區(qū)</b>點(diǎn)資料下載
    主站蜘蛛池模板: 黄色一级片播放| 国产做a爰片久久毛片a| 性欧美大战久久久久久久久| 在线天堂中文有限公司| 香蕉色网| 日韩视频高清| 久久综合五月婷婷| 国产精品三级在线观看| www.妖精视频| 天天狠狠干| 国产chinesehd精品酒店| 六月丁香啪啪| 福利三区| 色婷婷综合激情| 久久性感美女视频| 成zzzwww日本免费| 深夜视频在线观看免费| 国产理论精品| 一二三区视频| 亚洲成人高清| 人人做人人澡人人人爽| 狠狠涩| 午夜寂寞在线一级观看免费| 国产精品午夜久久久久久99热| 好黄好猛好爽好痛的视频| 国产精品丝袜在线观看| 四虎一影院区永久精品| 久久综合九色综合精品| 夜夜夜网| 放荡的俄罗斯美女bd| 日本不卡视频在线视频观看| 婷婷色九月| 久久精品亚洲精品国产色婷| 午夜寂寞在线一级观看免费| 88av视频在线观看| 9久久99久久久精品齐齐综合色圆| 色婷婷电影| 艹久久| 91成人免费福利网站在线| 中文字幕亚洲综合久久2| 欧美色图俺去了|