最近看qemu**的機會比較多,發現裡面用了大量巨集定義,有必要學習一下。剛開始主要關注了帶引數巨集的巨集展開次序,發現了之前沒有注意到的東西。
一般而言,我們在呼叫乙個帶引數巨集時,如果傳入的引數也是乙個帶引數巨集的話,我們期待的是像函式呼叫那樣,從內層到外層依次展開,依次計算出結果後,將內層巨集展開後的結果作為實參交給更外層的巨集進行處理,因為我們認為最內層的括號優先順序最高,應該被優先處理。大多數情況下,這個結論是正確的,但如果外層的巨集展開後有 '#' 或 "##" 運算子操作,則會優先從該層展開,這種情況下,在巨集展開的過程中往往會報錯。正確的做法是,要麼將巨集展開後帶有 '#' 或 "##" 操作的巨集放入最內層,要麼在這樣的巨集外面再包裹一層,並且呼叫包裹後的巨集。下面介紹幾個示例來說明這個問題:
假設有下面三個巨集:
#define a(a) a
#define b(a) -a
#define c(a,b) a ## b
則以下呼叫均會在預處理時出錯:
int a = c(1, a(b(2)));
a = c(a(b(1)), 2);
a = a(c(1, b(2)));
a = a(c(b(1), 2));
a = b(c(1, a(2)));
a = b(c(a(1),2));
但如果是以下面這種方式呼叫就不會報錯:
int a = a(b(c(1,2)));
或者是:
#define e_5 100
#define d(d) _5
#define cc(a, b) c(a,b)
int a = a(cc(e,d(d)));
上述**中為什麼要定義巨集e_5,是因為對於gcc而言,用##操作後的結果必須是乙個已經預定義過的符號。 C語言中的帶引數巨集
c語言中的帶引數巨集 一.帶引數的巨集 1.帶引數的巨集定義不是簡單的字串替換,還要進行引數替換 定義格式為 define 巨集名 參數列 字串 1 字串包含括號中所有指定的引數 eg define s a,b a b area s 3,2 2 編譯系統處理帶引數的巨集名時,按程式行中指定的字串,括...
C語言的巨集之帶引數巨集
c語言允許巨集帶有引數。在巨集定義中的引數稱為形式引數,在巨集呼叫中的引數稱為實際引數,這種巨集外形和作用與函式類似,即類函式巨集。但是它的行為和函式呼叫完全不同。對帶引數的巨集,在呼叫中,不僅要巨集展開,而且要用實參去代換形參。類函式巨集定義的圓括號中可以有乙個或多個引數,隨後這些引數出現在替換體...
mysql巨集引數 C語言帶引數的巨集定義
c語言允許巨集帶有引數。在巨集定義中的引數稱為 形式引數 在巨集呼叫中的引數稱為 實際引數 這點和函式有些類似。對帶引數的巨集,在展開過程中不僅要進行字串替換,還要用實參去替換形參。帶參巨集定義的一般形式為 define 巨集名 形參列表 字串 在字串中可以含有各個形參。帶參巨集呼叫的一般形式為 巨...