14

我在两本著名的 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);
  • 这是通过第 448 页的 ansi c - E. balagurusamy 编程。

当然,两个引文相互矛盾。据我所知,第一个是真的,我的编译器给了我这样的结果。但第二本书也广为人知。我想知道以前版本的 c 中是否有这样的东西,或者第二次引用是错误的。

4

2 回答 2

23

第二本书是错误的:很容易检查宏不会像那样扩展。但是,您可以通过使用预处理器运算符对标记进行字符串化#来获得它们所描述的效果:

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

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

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

这是ideone 上工作示例的链接

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

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

于 2012-06-27T18:11:18.923 回答
3

书是对的。因为是时候了。我写了一个小测试程序来验证它(在你编程之前你不会喜欢文本编辑器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 中正式发布。

于 2016-04-21T11:58:35.543 回答