您的位置:首页 > 编程语言 > C语言/C++

C语言中的宏

2015-08-05 09:08 369 查看
酷壳的一篇文章中看到这样一个题目:
>下面这段代码的输出结果是:
>

include <stdio.h>

#define f(a,b) a##b
#define g(a)   #a
#define h(a) g(a)
int main()
{
printf("%s\n", h(f(1,2)));
printf("%s\n", g(f(1,2)));
return 0;
};

> 当然,你首先要了解##和#的用法,如果不懂的话,本题你可以直接跳过。
> 解答:
>看到这段程序你可能会认为,这两个printf输出的同一个结果,可是答案却非如此,本题的输出是12和f(1,2),为什么会这样呢?因为这是宏,宏的解开不象函数执行,由里带外。

文章作者给出的解释很简单,这里给出详细的解释,方便大家理解。

和#的用法

首先我们得弄清楚##和#的用法,在C语言中参数名以#作为前缀则结果将被扩展为由实际参数的带引号的字符串,也就是说不管实参传入的是什么都将输出一个字符串。而##则提供了一种连接实参的手段,就是把多个实参连接起来作为一个整体。

宏的展开次序

如果宏有参数,如
h(a)
中的
a
我们称之为形参,而宏的实际参数我们称之为实参,如
h(f(1,2))
中的
f(1,2)
。宏的展开简单来说可以分成三步:

首先用实参替换形参,将实参代人宏文本中

如果实参也是宏则展开实参

处理宏替换后的宏文本,若宏文本也包含宏则继续展开,否则完成展开。

这里有个例外,也是理解本题的重点。第一步将实参代入后,如果遇到字符“#”或“##”,即使实参是宏,也不再展开实参,而是当作文本处理。即凡宏定义里有‘#’和‘##’的地方宏参数不再展开。

详细解答

有了上面两个关于宏的基础知识,我们就可以正确理解这道题了。

首先来看
h(f(1,2))
,代入实参
f(1,2)
g(a)
中得到
g(f(1,2))
,这时没有遇到#,继续展开实参得到
g(12)
,接下来展开宏
g
得到一个字符串,该字符串就是
f(1,2)
展开的内容。详细展开过程如下:

h(f(1,2))

g(f(1,2))

g(#12)

12

接下来看
g(f(1,2))
,代人实参
f(1,2)
得到
#f(1,2)
,这时遇到了#就会把
f(1,2)
当做文本处理,不会继续展开,输出的结果就是字符串f(1,2)详细展开过程如下:

g(#f(1,2))

f(1,2)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: