2013-03-26 17 views
1
gcc 4.7.2 
c89 

你好,使用函數式的馬科斯,有什麼問題?

函數宏只是文本替換,我知道有些程序員喜歡內聯函數。我想知道我所做的是否有任何問題。

只需注意兩點,我沒有使用do ... while(0)或大括號來包裝,因爲我會得到isdn_channel的非聲明錯誤。

#define ISDN_CHANNEL_GET(channel)          \ 
    module_isdn_channel_t *isdn_channel = NULL;       \ 
    isdn_channel = channel->base.imp->isdn_channels[channel->isdn_id]; \ 
    if(!isdn_channel) {             \ 
     LOG(CRITICAL, "Failed to get channel data");     \ 
     return FALSE;             \ 
    } 

而且在我的源代碼,我用它這樣的,不加分號:

ISDN_CHANNEL_GET(channel) 
isdn_channel->base.sync_answer |= SIP_CONNECTED; 

一切工作正常,但我只是想檢查我剛剛進入寫這些功能像宏。

非常感謝您的任何建議,

+2

有趣的事情會發生,當你寫1行'if'或'for'沒有'{}',並且宏是那一行。有一個'do {code} while(0)'成語來防止這種事情發生。 – nhahtdh 2013-03-26 11:05:20

+0

你應該回到那個宏嗎?正如你所說,它是一個文本替代品,而不是一個功能。 – Daboyzuk 2013-03-26 11:05:22

回答

3

沒問題的中間返回,只要你不」 t如下所示: if(condition) ISDN_CHANNEL_GET(channel)

用do ... while(0)來包裝你的宏以避免這個問題。

+0

+1,在調用宏後單獨進行檢查會更好,但問題不僅出現在if#/ else結構中,而且在本例中已經存在違反了通常的語法期望:看起來像函數調用的東西應該具有與之相同的語法規則。不僅編輯們懷疑'ISDN_CHANNEL_GET'這個陳述將會延續到下一行,而且任何不經意的讀者都會這樣認爲。所以你的代碼真的很難遵循。 – 2013-03-26 14:18:36

1

每次call這個函數宏,它會被擴大時 - 你優化時間,但沒有空間:-)。編譯時它肯定會擴大你的應用程序的大小。

我的第一定律:「你可以優化空間或優化時間 - 但不是時間和空間」

3

請不要在宏中使用的回報。

我們知道,宏告訴預處理器,以取代無論是在之後的#define ..

,這樣你們可以在不知不覺中在功能

+0

如果數據爲NULL,我會立即返回,因爲我無法繼續。 – ant2009 2013-03-26 17:05:18

+0

在這種情況下,如果(!isdn_channel) – hazzelnuttie 2013-03-27 05:24:55

2

這裏還有其他的問題,後jbgs和Manimehalai提到的那些:

  • 宏觀參數(在這裏你使用它的兩倍)
  • 運算符優先級的多元評價(總是使用括號周圍參數)
  • 缺乏打字(打字使用盡可能多的,你可以的,編譯器是你的朋友)

前兩個是殺手,只要你在更complicat通ed表達式作爲參數,也可能包含副作用。當你傳遞一個指向具有同名字段的結構的指針時,第三個字節將會以字節爲單位,例如,但它會做一些完全不同的事情。

你的例子實際上是編寫具有相同功能的inline函數的微不足道的例子。編譯器可以幫助你調試你的代碼,如果你這樣做,總是使用編譯器而不是針對它。