寫一個簡單的宏定義:
#define MIN(a,b) ((a) > (b) ? (a) : (b))
指令與作用:
# 空指令,無任何效果
#define 定義宏
#undef 取消已定義的宏
#if 如果給定條件為真应狱,則編譯下面代碼
#ifdef 如果宏已經(jīng)定義疾呻,則編譯下面代碼
#ifndef 如果宏沒有定義,則編譯下面代碼
#elif 如果前面的#if給定條件不為真尉咕,當(dāng)前條件為真璃岳,則編譯下面代碼
#endif 結(jié)束一個#if……#else條件編譯塊
#error 停止編譯并顯示錯誤信息
運(yùn)算符:
例如: #define demo1(n) "123"#n
出現(xiàn)在宏定義中的#運(yùn)算符把跟在其后的參數(shù)轉(zhuǎn)換成一個字符串。有時把這種用法的#稱為字符串化運(yùn)算符
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%s",demo1(abc));
}
//打印會輸出 123abc
例如:#define demo2(m,n,j) m##n##j
##運(yùn)算符用于把參數(shù)連接到一起晦款。預(yù)處理程序把出現(xiàn)在##兩側(cè)的參數(shù)合并成一個符號
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%d",demo2(1, 2, 3));
}
//打印會輸出 123
VA_ARGS 是一個可變參數(shù)的宏枚冗,很少人知道這個宏,這個可變參數(shù)的宏是新的C99規(guī)范中新增的坛怪,目前似乎只有g(shù)cc支持(VC6.0的編譯器不支持)股囊。
實現(xiàn)思想就是宏定義中參數(shù)列表的最后一個參數(shù)為省略號(也就是三個點(diǎn))。這樣預(yù)定義宏_ VA_ARGS _就可以被用在替換部分中居灯,替換省略號所代表的字符串。比如:
#define PR(...) printf(__VA_ARGS__)
int main()
{
int wt=1,sp=2;
PR("hello\n");
PR("weight = %d, shipping = %d",wt,sp);
return 0;
}
輸出結(jié)果:
hello
weight = 1, shipping = 2
省略號只能代替最后面的宏參數(shù)义锥。
#define W(x,…,y)錯誤岩灭!
注意:##__VA_ARGS__ 宏前面加上##的作用在于,當(dāng)可變參數(shù)的個數(shù)為0時柱恤,這里的##起到把前面多余的","去掉的作用,否則會編譯出錯
宏定義的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
提高了程序的可讀性膨更,同時也方便進(jìn)行修改缴允,用戶只需要在一處定義,多處使用矗漾,修改也只需要修改一處
提高程序的運(yùn)行效率:使用帶參的宏定義既可完成函數(shù)調(diào)用的功能薄料,又能避免函數(shù)的出棧與入棧操作,減少系統(tǒng)開銷誊役,提高運(yùn)行效率谷市,如果有一個函數(shù)會在工程中頻繁使用,可以考慮一下宏定義
缺點(diǎn)
由于是直接嵌入的迫悠,所以代碼可能相對多一點(diǎn)
嵌套定義過多可能會影響程序的可讀性,而且很容易出錯艺玲;
對帶參的宏而言鞠抑,由于是直接替換,并不會檢查參數(shù)是否合法秒梳,存在安全隱患。
預(yù)編譯語句僅僅是簡單的值代替端幼,缺乏類型的檢測機(jī)制