c語言允許巨集帶有引數。在巨集定義中的引數稱為形式引數,在巨集呼叫中的引數稱為實際引數,這種巨集外形和作用與函式類似,即類函式巨集。但是它的行為和函式呼叫完全不同。對帶引數的巨集,在呼叫中,不僅要巨集展開,而且要用實參去代換形參。類函式巨集定義的圓括號中可以有乙個或多個引數,隨後這些引數出現在替換體中。
下面是乙個類函式巨集的示例:
#define square(x) x*x
在程式中可以這樣使用:
z=
square(2
);
這看上去像函式呼叫,但是它的行為和函式呼叫完全不同。
再看下面的示例:
/* mac_arg.c -- macros with arguments */
#include
#define square(x) x*x
#define pr(x) printf("the result is %d.\n", x)
intmain
(void
)
輸出結果如下,你的編譯器輸出甚至有可能與下面的結果完全不同。
x = 5
evaluating square(x): the result is 25.
evaluating square(2): the result is 4.
evaluating square(x+2): the result is 17.
evaluating 100/square(2): the result is 100.
x is 5.
evaluating square(++x): the result is 49.
after incrementing, x is 7.
程式中, square(2)替換為2*2
,x實際上起到引數的作用。前兩行與預期相符,但是接下來的結果有點奇怪。導致這樣結果的原因是預處理器 不做計算、不求值,只替換字串行。對於square(x+2),預處理器替換為x+2*x+2
。如果x=5,那麼表示式的值為:
5+2*5+2 = 5+10+2=17
巨集定義的時候多加幾個括號可以解決這樣的問題:
#define square(x) (x)*(x)
現在square(2)變成(x+2)*(x+2)
,可以得到正確結果。
但是加括號不能解決所有問題。最後一種情況的問題還是無法避免。
square(++x)
變成了++x*++x
,遞增了兩次,一次在乘法運算前,一次在乘法運算後:
++x*++x=6*7=42
由於標準並未對這類運算規定順序,所以有些編譯器得6*7
。而有些編譯器可能在乘法運算之前已經遞增了x,所以7*7
得49。在c標準中,對該表示式求值的這種情況稱為未定義行為。無論哪種情況,x的開始值是5,雖然從源**上看只遞增了一次,但是x的最終值是7。
解決這個問題最簡單的方法是,避免用++x作為巨集引數。一般而言,不要在巨集中使用遞增或遞減運算子。但是,++x可作為函式引數,因為編譯器會對++x求值後,再把5傳給函式。
mysql巨集引數 C語言帶引數的巨集定義
c語言允許巨集帶有引數。在巨集定義中的引數稱為 形式引數 在巨集呼叫中的引數稱為 實際引數 這點和函式有些類似。對帶引數的巨集,在展開過程中不僅要進行字串替換,還要用實參去替換形參。帶參巨集定義的一般形式為 define 巨集名 形參列表 字串 在字串中可以含有各個形參。帶參巨集呼叫的一般形式為 巨...
C語言基礎之帶引數的巨集
像函式的巨集 define cube x x x x 巨集可以帶引數 例 include define cube x x x x int main int argc,char const ar 在這個巨集中,編譯預處理時,會將所有的cube x 替換成 x x x 其中x是引數 錯誤定義的巨集 de...
C語言中的帶引數巨集
c語言中的帶引數巨集 一.帶引數的巨集 1.帶引數的巨集定義不是簡單的字串替換,還要進行引數替換 定義格式為 define 巨集名 參數列 字串 1 字串包含括號中所有指定的引數 eg define s a,b a b area s 3,2 2 編譯系統處理帶引數的巨集名時,按程式行中指定的字串,括...