基礎知識 | 每日一面(71)

古代的劍客們與

對手相逢時,無

論對手多麼強大,

明知不敵,也要亮出自己的劍!

讀者:我試圖用 ANSI 「字符串化」 預處理操作符 # 向信息中插入符號

常量的值, 但它字符串化的總是宏的名字而不是它的值。

小林;你可以用下面這樣的兩步方法迫使宏既字符串化又擴展:

#define Str(x) #x

#define Xstr(x) Str(x)

#define OP plus

char *opname = Xstr(OP);

這段代碼把 opname 置為 「plus」 而不是 「OP」。在使用符號粘接操作符 ## 連接兩個宏的值 (而不是名字) 時也要採用同樣的「迂迴戰術」。

讀者:警告信息 「warning: macro replacement within a string lit-eral」 是什麼意思?

小林:有些 ANSI 前的編譯器/預處理器把下面這樣的宏

#define TRACE(var, fmt) printf("TRACE: var = fmtn", var)

解釋為

TRACE(i, %d);

這樣的調用會被擴展為

printf("TRACE: i = %dn", i);

換言之, 字符串常量內部也作了宏參數擴展。K&R 和標準 C 都沒有定義這樣的宏擴展。當你希望把宏參數轉成字符串時,你可以使用新的預處理操作符 # 和字符串常量連接:

#define TRACE(var, fmt)

printf("TRACE: " #var " = " #fmt "n", var)

有時候,正是那些意想不到之人,成就了無人能成之事。

——圖靈