關於macro的介紹,有一個還不錯的網站。
在debug的時候很常用printf來debug,並且會註明這是哪一個變數名稱,用macro可以很容易作到。
#define print_var(var) printf("%s: %s\n", #var, var)
//也可以這樣
#define PRINT_TOKEN(token) printf(#token " is %d", token)
char s[] = "aaa";
//s: aaa
print_var(s);
int a = 5;
//a is 5
PRINT_TOKEN(a);
如果想要一次印出多個變數,可以這樣做。
#define print_var(var) do { printf("%s: %s\n", #var, var); } while (0)
#define print_three_var(var) do { \
print_var(var); \
print_var(var##2); \
print_var(var##3); \
} while (0)
int s = 10;
int s2 = 20;
int s3 = 30;
print_three_var(s);
//印出s: 10
// s2: 20
// s3 :30
也可以印出struct裡面的變數。
#define BUILD_FIELD(field) my_struct.inner_struct.union_a.##field
//會被展開成
my_struct.inner_struct.union_a.field1
使用macro會有一些陷阱
#define MULT(x, y) x * y
#define ADD_FIVE(a) (a) + 5
MULT(1+1,2+2); //會被展開成1+1*2+2,結果不對。
ADD_FIVE(3)*3 //會被展開成(3)+5*3,結果不對。
上述的結果有誤,可以改成
#define MULT(x,y) (x)*(y)
#define ADD_FIVE(a) ((a) + 5)
MULT(1+1,2+2); //會被展開成(1+1)*(2+2),結果正確。
ADD_FIVE(3)*3 //會被展開成((3)+5)*3,結果正確。
經驗法則是最好每個element都把它包起來。
一個SWAP的trick。
//可以試著驗證看看
#define SWAP(a, b) do {a ^= b; b ^= a; a ^= b; } while(0)//最好把它包起來,不然的話會很容易不小心把後兩句給排除掉。加上do while是為了有分號。
if (a>0)
SWAP(a,b);
else
SWAP(a,b);
注意不要搭配side-effect服用,像這樣。
#define MAX(a, b) ((a) < (b) ? (b) : (a))
int x = 5, y = 10;
//因為macro是直接展開,並不是x++,y++做完之後才展開。
int z = MAX(x++, y++);
//所以會變成int z = (x++ < y++ ? y++ : x++)
如果不想寫多行的話要怎麼做?
//用一個slash表示接到下一行
#define SWAP(a, b) { \
a ^= b; \
b ^= a; \
a ^= b; \
}
其它還有,
#ifndef __cplusplus
//這個指令將"中斷編譯"過程並返回一個參數中定義的出錯資訊
#error A C++ compiler is required
#endif
若是想要取消macro呢?
#define MAX_WIDTH 100
char str1[MAX_WIDTH];
#undef MAX_WIDTH
#define MAX_WIDTH 200
char str2[MAX_WIDTH];
一個較為複雜的例子,
#if MAX_WIDTH>200
#undef MAX_WIDTH
#define MAX_WIDTH 200
#elif MAX_WIDTH<50
#undef MAX_WIDTH
#define MAX_WIDTH 50
#else
#undef MAX_WIDTH
#define MAX_WIDTH 100
#endif
char str[MAX_WIDTH];