在引用的字符串中扩展宏变量

时间:2012-06-27 17:50:09

标签: c string macros c-preprocessor

我在c中的两本着名书籍中发现了两件不同的东西, 第一个是 “宏观扩展中的引用字符串中不会替换正式参数” - 由K& R c语言第76页

第二个是代码,

#define PRINT(var,format) printf("variable is %format\n",var)
PRINT(x_var,f);

以后的宏调用将扩展为

printf("x_var is %f\n",x_var);
  • 这是通过编程在ansi c - E. balagurusamy在448页。

肯定有两个引用是相互矛盾的。到目前为止,我知道第一个是真的,我的编译器给我的结果如此。但第二本书也是众所周知和受欢迎的。我想知道在先前版本的c中是否有这样的东西,或者第二次引用是假的。

2 个答案:

答案 0 :(得分:19)

第二本书是错误的:it is easy to check宏不会像那样扩展。但是,您可以使用#预处理程序运算符来获得 stringizing 标记所描述的效果:

#define PRINT(var,format) printf(#var" is %"#format"\n",var)

现在您可以按如下方式打印变量:

int xyz = 123;
PRINT(xyz, d);

这是a link to a working sample on ideone

请注意在'#format'之前和之后添加双引号,在'var'和'format'之前添加'#'。 '#'运算符使变量的值成为带引号的字符串 - 带有双引号。这使得替换的字符串成为一行中的四个带引号的字符串,C编译器将其识别为连接成一个字符串的请求。因此字符串:“xyz”,“is%”,“d”和“\ n”连接成:“xyz is%d \ n”

(请注意,此示例与原始问题中的示例的不同之处在于,orignal示例具有“变量为...”,其中答案将“变量”替换为“var”宏参数的实例)

答案 1 :(得分:2)

这本书是对的。这是时候了。我写了一个小测试程序来验证它(在ed编程之前,你不欣赏文本编辑器):

#define PRINT(fmt,val) printf("val = %fmt\n", (val))
main()
{
    int x;
    x = 5;
    PRINT(d, x);
}

我在运行Unix V6的PDP-11上编译了它。运行程序会产生以下输出:

x = 5

这甚至在K& R C之前。“特征”在C的后续迭代中被删除,并在ISO C90中正式发布。