C++中巨集定義的使用注意事項
1 簡介
巨集定義是C語言的三種預處理功能之一,另外兩種預處理是檔案包含和條件編譯。
1.1 格式
巨集定義的格式分為不帶引數和帶引數兩種。
不帶引數的格式為
#define 巨集名 字串
帶引數的格式為
#define 巨集名(引數表) 字串
1.2 使用
巨集展開是在預處理階段完成的,這個階段把巨集名只是看作一個字串,並不會有任何的計算髮生。展開時,在巨集名出現的地方只是簡單地使用串來代替,並不會增添任何的符號。
2 使用時的注意事項
2.1 使用帶引數的巨集定義時,要使用完備的括號
由於巨集定義只是簡單的字元替換,巨集的引數如果是複合結構,如果不使用括號,可能會產生意想不到的情況。如
#define ADD(a, b) a+b
或者
#define ADD(a, b) (a)+(b)
此時如果要計算ADD(a,b)*ADD(a,b),則會變成
a+b*a+b
或者
(a)+(b)*(a)+(b)
因此,對於巨集定義要使用完備的括號
#define ADD(a, b) ((a)+(b))
2.2 使用巨集定義時,不允許引數發生變化
如果在使用巨集定義時,引數進行了自增或者自減變化,則在巨集定義展開時對其引數的多次自增或自減變化,導致意想不到的情況。如
#define SQUARE(a) ((a)*(a))
int nValue = 10;
int nSquare = SQUARE(nValue++);
此時,nSquare的值是
所以,為了避免出現這種情況,最簡單有效的方法是保證巨集定義的引數不發生變化。
2.3 用大括號將巨集定義的多條表示式括起來
如果巨集定義包含多條表示式,一定要用大括號將其括起來。如果沒有這個大括號,巨集定義中多條表示式很可能只有一條會被執行。
#define INIT(a, b, c) a=0;b=1;c=2;
for(int i=0; i<10; ++i)
INIT(A[i].a, B[i].b, C[i].c);
簡單的字元代替,for迴圈變為
for(int i=0; i<10; ++i)
A[i].a = 0;
B[i].b = 1;
C[i].c = 2;
此時,程式會因為i超出作用域範圍而報錯。如果把INIT巨集寫成
#define INIT(a, b, c) {a=0;b=1;c=2;}
則可以完成對A、B、C陣列的初始化。