欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
C語(yǔ)言的宏定義用起來(lái)有什么要注意的?為什么很多宏用do{}while(0)包圍?

https://www.toutiao.com/a6713691650176057611/

謝邀。

C語(yǔ)言中的 define 宏定義可以像函數那樣接收參數(這種宏定義常被稱(chēng)作“函數式宏定義”),不過(guò)不能像函數那樣提供參數的類(lèi)型檢查,這個(gè)特點(diǎn)在有些程序員看來(lái)是不安全的。

C語(yǔ)言中的“函數式宏定義”

但是,函數式宏定義不關(guān)心參數類(lèi)型這個(gè)特點(diǎn),有時(shí)候也會(huì )被利用起來(lái),寫(xiě)出一些適用性更廣的C語(yǔ)言代碼,例如:

上面這段C語(yǔ)言宏定義代碼實(shí)現了一個(gè) max() 方法,它接收兩個(gè)參數,并返回較大的那個(gè)參數,max() 方法不關(guān)心參數的類(lèi)型,因此 __a 和 __b 可以是 int 型的,也可以是 char 型或者 double 型以及其他數據類(lèi)型的。

如果使用 max() 方法提供的功能以C語(yǔ)言函數的方式來(lái)寫(xiě),就稍顯麻煩些了,程序員不得不為每一種數據類(lèi)型實(shí)現一個(gè) max() 函數。更加糟糕的是,C語(yǔ)言并不支持函數的重載,因此 max() 這個(gè)函數名一旦被使用,其他函數就不能再使用了,因此相關(guān)的C語(yǔ)言代碼可能是下面這樣的:

這樣對比起來(lái),顯然使用 define 宏來(lái)定義 max() 方法更加方便一些。不過(guò),C語(yǔ)言中的宏定義不提供參數類(lèi)型檢查的確也是一個(gè)缺點(diǎn),它可能會(huì )導致程序的不安全,讀者不應忽視這一點(diǎn)。因此如果不是必須要使用 define 宏定義才能解決問(wèn)題,應該盡可能的使用函數,若是希望能夠得到較高效率的代碼,可以使用 inline 函數。

關(guān)于 inline 函數,我之前的文章較為詳細的討論過(guò)。

使用C語(yǔ)言中宏定義的注意事項

C語(yǔ)言中的“函數式宏定義”雖然使用起來(lái)很像函數,但它實(shí)際上并不是函數,讀者千萬(wàn)不能忽視這一點(diǎn),不然可能會(huì )寫(xiě)出具有隱患,甚至嚴重錯誤的C語(yǔ)言程序。請看下面這個(gè)例子:

上面這段C語(yǔ)言代碼編譯并執行,會(huì )輸出什么呢?

在 main() 函數中,變量 a 和 b 都被初始化為 2。接著(zhù)調用了 max() 宏,傳遞的參數分別是 ++a 和 b,粗略來(lái)看,此時(shí)執行 max(++a, b),就相當于執行 max(3, 2),那上面這段C語(yǔ)言程序會(huì )輸出 3, 2, 3 了?得到答案最簡(jiǎn)單粗暴的方法就是編譯并執行這段代碼,請看:

沒(méi)有經(jīng)驗的讀者看到實(shí)際輸出估計會(huì )大吃一驚,a 和 m 怎么不是 3 而是 4 呢?并沒(méi)有第二處給 a 再加一???上一節曾討論,編譯器會(huì )將C語(yǔ)言中的宏定義展開(kāi)到被調用處,而不是像函數那樣編譯后,再通過(guò) call 指令調用。使用 gcc -E 命令查看編譯器將上述C語(yǔ)言代碼預處理后的代碼,得到如下結果,請看:

顯然,這里就是C語(yǔ)言中“函數式宏定義”的注意事項了,傳遞給 max() 的參數 ++a 會(huì )被展開(kāi)到宏定義中所有的 __a 處,這就解釋了為何 a 和 m 最后都等于 4 而不是 3 了。

“函數式宏定義”還有其他與真正函數不同的地方,例如“函數式宏定義”就不適合用于遞歸等。

使用 do{}while(0)包裹代碼

盡管C語(yǔ)言中的“函數式宏定義”和真正的函數相比有一些缺點(diǎn),但只要小心使用還是會(huì )顯著(zhù)提高代碼的執行效率的,畢竟省去了分配和釋放棧幀、傳參、傳返回值等一系列工作。正因為如此,Linux 內核中有相當多的方法是使用 define 宏定義實(shí)現的,并且,在內核C語(yǔ)言代碼中,“函數式宏定義”經(jīng)常借助 do{}while(0) 實(shí)現,例如:

為什么要用 do{}while(0) 包裹C語(yǔ)言代碼呢?不使用 do{}while(0) 包裹起來(lái)有什么不好嗎?請看下面這幾行C語(yǔ)言代碼:

宏定義被編譯器展開(kāi)后,會(huì )產(chǎn)生下面這樣的C語(yǔ)言代碼:

這可能就與程序員的意圖不一致了,這種情況下__release(lock); 并沒(méi)有在 if(cond) 的作用范圍內??赡茏x者會(huì )說(shuō),那像函數一樣,使用 {} 包裹代碼不就可以了嗎?請再來(lái)看看下面這幾行C語(yǔ)言代碼:

問(wèn)題就出在 spin_unlock(lock); 后面的這個(gè)分號“;”,如果不寫(xiě)就不像函數調用,如果寫(xiě)了就會(huì )引發(fā)語(yǔ)法錯誤——if 語(yǔ)句會(huì )被這個(gè)“;”提前結束,else 無(wú)法與其配對。這么看來(lái),在C語(yǔ)言的“函數式宏定義”中使用 do{}while(0) 包裹C語(yǔ)言代碼顯然就是一個(gè)不錯的方法了。

小結

“函數式宏定義”并不是真正的函數,它與真正的函數是有區別的,如果弄不清楚這一點(diǎn),很容易迷惑。在最后,我們一起分析了常用 do{}while(0) 包裹宏定義的代碼的原因,讀者今后在C語(yǔ)言程序開(kāi)發(fā)中,也可以使用該技巧。



https://www.toutiao.com/a6713691650176057611/

宏定義是一種替換類(lèi)型的語(yǔ)句,屬于低安全性操作,所以在設計里面宏一般用于數值替換,在不得不進(jìn)行函數動(dòng)態(tài)鏈接的時(shí)候才會(huì )使用宏函數。

在能不使用宏的情況下,盡量避免使用宏,因為宏的命令在匯編中被直接替換掉,甚至被優(yōu)化掉,所以難以進(jìn)行debug。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
一個(gè)宏定義看看你的 C語(yǔ)言級別
不可小看的技術(shù)——C語(yǔ)言中的“宏”
宏、內聯(lián)函數和普通函數的區別
C/C++之define用法小結
Linux 內核代碼奇技淫巧你見(jiàn)過(guò)多少?C語(yǔ)言 define宏定義總結一下
宏函數與自定義函數的區別
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久