C語言中帶引數巨集的展開次序

2021-10-10 17:52:47 字數 936 閱讀 1567

最近看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 巨集名 形參列表 字串 在字串中可以含有各個形參。帶參巨集呼叫的一般形式為 巨...