宏定義
不帶參數
宏定義又稱為宏代換、宏替換,簡稱“宏”。
格式:
#define 標識符 字符串
其中的標識符就是所謂的符號常量,也稱為“宏名”。
預處理(預編譯)工作也叫做宏展開:將宏名替換為字符串。
掌握”宏”概念的關鍵是“換”。一切以換為前提、做任何事情之前先要換,準確理解之前就要“換”。
例:
#define Pi 3.1415926
把程序中出現的Pi全部換成3.1415926
帶參數(宏函數)
宏名之后帶括號的宏被認為是宏函數。用法和普通函數一樣,只不過在預處理階段,宏函數會被展開。優點是沒有普通函數保存寄存器和參數傳遞的開銷,展開后的代碼有利于CPU cache的利用和指令預測,速度快。缺點是可執行代碼體積大。
和不帶參數的宏定義一樣,除了一般的字符串替換,還要做參數代換。
格式:
#define <宏名> (<參數表>) <宏體>
例如:
#define S(a,b) a*b
area=S(3,2);第一步被換為area=a * b; ,第二步被換為area=3 * 2;
(1)實參如果是表達式容易出問題
例如:
#define S(r) r*r
area=S(a+b);第一步換為area=r * r;,第二步被換為area=a+b * a+b;
正確的宏定義是#define S(r) ((r)*(r))
(2)帶參宏一般用法
例如:
#define MIN(A, B) A < B ? A : Bint a = 2 * MIN(3, 4);
printf("%d", a);
展開結果:
int a = 2 * MIN(3, 4);
//=> int a = 2 * 3 < 4 ? 3 : 4;
//=> int a = 6 < 4 ? 3 : 4;
//=> int a = 4;
正確如下:
#define MAX(a,b) ((a)>(b)?(a):(b))
則遇到MAX(1+2,value)則會把它替換成:
((1+2)>(value)?(1+2):(value))
(3)有參宏定義中#的用法
需要注意的是凡宏定義里有用’#’或’##’的地方宏參數是不會再展開,被當做字符串處理
#define STR(str) #str
“#”號用于把宏定義中的參數兩端加上字符串的”“
比如,這里 STR(my#name) 會被替換成”my#name”
(4)有參宏定義中##的用法
例如:
#define WIDE(str) L##str
則會將形參str的前面加上L
比如:
WIDE(“abc”)就會被替換成L”abc”
如果有:
#define FUN(a,b) vo##a##b()
那么FUN(id ma,in)會被替換成void main()
多行宏定義
每一次換行都必須要有 “ \ ”結尾,末尾行不需要“ \ ” 結尾。
例如:
#define doit(m,n) for(int i=0;i<(n);++i)\
{\
m+=i;\
}
#define WARN_IF(EXP) \do { if (EXP) \fprintf (stderr, "Warning: " #EXP "\n"); } \while (0)
WARN_IF (x == 0);會被擴展成:
do
{ if (x == 0)fprintf (stderr, "Warning: " "x == 0" "\n");
}
while (0);
#define VAR_TO_STR(var)\({\std::string name = (#var);\int pos = 0;\int length = 0;\length = name.length();\pos = name.find_last_of(':',length);\if ( pos == -1 )\{\pos = 0;\name = name.substr(pos,length);\}\else\{\name = name.substr( pos + 1,length);\}\(name);\})
std::string str = VAR_TO_STR(VDAD::RRR) 展開后:
int main()
{std::string ss =({std::string name = ("VDAD::RRR");int pos = 0;int length = 0;length = name.length();pos = name.find_last_of(':',length);if ( pos == -1 ){pos = 0;name = name.substr(pos,length);}else{name = name.substr( pos + 1,length);}(name);});cout << ss<< endl;return 0;
}
輸出為:
相關鏈接
1.C語言宏的特殊用法和幾個坑
2.C/C++ 宏定義