# 將巨集參數轉換為字串常值。
#include <stdio.h>
#define P(A) printf("%s:%d\n", #A, A)
int main(void)
{
int a = 1, b = 2;
P(a); // 輸出:a:1
P(b); // 輸出:b:2
P(a+b); // 輸出:a+b:3
return 0;
}
巨集展開:P(a) → printf("%s:%d\n", "a", a);
#define SQR(x) printf("The square of " #x " is %d.\n", (x)*(x))
SQR(8); // 輸出:The square of 8 is 64.
若無 #,"The square of x" 中的 x 會被視為普通字元而非參數。
## 將兩側標記合併為單一標記(必須形成合法 C 標記)。
#define XNAME(n) x ## n
XNAME(8) // 展開為:x8
int XNAME(5) = 10; // 展開為:int x5 = 10;
#define DECLARE_ARRAY(name, size) int name ## _arr[size]
#define INIT_ARRAY(name, value) for(int i=0;i
#define CASE(x, y) case x: _bsd_setlasterror(anApplInstance, BSD_ ## y); break
// 使用:
switch (err) {
CASE(EINVAL, EINVAL);
CASE(ENOMEM, ENOMEM);
}
// 展開為:
// case EINVAL: _bsd_setlasterror(anApplInstance, BSD_EINVAL); break;
// case ENOMEM: _bsd_setlasterror(anApplInstance, BSD_ENOMEM); break;
## 將 BSD_ 與參數 y 粘合為 BSD_EINVAL 等完整常數名。
1 ## 2、int ## x)。## 會阻止參數展開,需雙層巨集間接粘合:#define PASTE(a, b) a ## b
#define PASTE_INDIRECT(a, b) PASTE(a, b)
#define VALUE 123
PASTE_INDIRECT(VALUE, 456) // 正確展開為 123456
// PASTE(VALUE, 456) 會嘗試粘合 "VALUE" 與 "456" → "VALUE456"(非預期)
#define LOG_VAR(var) printf(#var " = %d\n", var)
#define MAKE_FUNC(name) void name ## _func(void) { LOG_VAR(name); }
MAKE_FUNC(foo) // 生成 void foo_func(void) { printf("foo" " = %d\n", foo); }
| 運算符 | 功能 | 典型用途 |
|---|---|---|
# | 參數字串化 | 除錯列印、自動生成字串常值 |
## | 標記粘合 | 自動生成識別符、建構複合名稱、巨集元程式設計 |
善用這兩個運算符能大幅減少重複程式碼,實現類似模板的元程式能力,但過度使用會降低可讀性,建議配合完整註解並控制在合理範圍內。