­

基础知识 | 每日一面(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)

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

——图灵