可以使用#define僞指令定義一個宏,宏分為帶參數的宏和不帶參數的宏。宏定義以#define關鍵字後面第一個出現的第一個連續字元序列作為宏,剩下的部分作為宏體。宏定義具有檔案作用域,不論宏定義出現在檔案中的那個地方(如函數體内,類型定義内部,名字空間内部等),在它後面的任何地方都可以引用宏。
宏的特點和注意事項:
(1)宏定義的不是語句,是以不需要使用語句結束符“;”,否則它會被看做宏的一部分。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define WRITE(x,y) (x+y)
int main()
{
WRITE(2, 3);
printf("%d\n", WRITE(2, 3));
system("pause");
return 0;
}
(2)任何宏在編譯預處理階段都隻是進行簡單的文本替換,不做類型檢查和文法檢查,這個工作留個編譯器進行。參數替換法生在宏擴充之前。
(3)宏可以嵌套定義。
#define PI 3.14
#define PI_2 (2*PI)
(4)宏不可以調試,因為宏不會進入符号表(符号表是編譯器建立的,在編譯時宏已經消失了),即使宏替換後出現了文法錯誤,編譯器也會将錯誤定位在源程式中而不是定位到具體的某個宏定義中。
(5)程式裡使用雙引号括起來的字元串中即使出現了與宏同名的子串,預處理過程也不進行替換。
(6)定義帶參數的宏時,宏名和左括号之間不能出現空格,否則使用時會出現問題,但是編譯器不會檢查出這種錯誤。
錯誤的:
#define TEXT (str)#str
宏引用:
TEXT(hello bit);
擴充為:
(str)#str(hello bit);
正确的:
#define TEXT(str) #str
(7)帶參數的宏和各個參數應該分别用括号括起來,以免造成意想不到的錯誤。
應該寫成這樣:
#define ADD(x) ((x)+(x))
如果寫成:
#define MPLIT(x) x*x
就極有可能因為運算優先級的問題造成錯誤。語句:
a=MPLIT(3+5);
将被擴充為:
a=3*5+3*5;
很明顯出現了錯誤!
注意:在定義宏的過程中千萬不要吝啬括号。
(8)不要在引用宏定義的參數清單中使用自增和自減運算符,否則可能導緻變量多次求值,其結果可能與預期不符,因為複合表達式中的求值順序可能因為編譯器的不同而不同。例如:
int n=5;
int w=MPLIT(n++);
其結果可能是25,也可能是30。
#undef MPLIT