C語言的巨集之帶引數巨集

2021-10-07 12:53:03 字數 1728 閱讀 8135

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 編譯系統處理帶引數的巨集名時,按程式行中指定的字串,括...