C语言中的宏
2015-08-05 09:08
369 查看
在酷壳的一篇文章中看到这样一个题目:
>下面这段代码的输出结果是:
>
> 当然,你首先要了解##和#的用法,如果不懂的话,本题你可以直接跳过。
> 解答:
>看到这段程序你可能会认为,这两个printf输出的同一个结果,可是答案却非如此,本题的输出是12和f(1,2),为什么会这样呢?因为这是宏,宏的解开不象函数执行,由里带外。
文章作者给出的解释很简单,这里给出详细的解释,方便大家理解。
首先用实参替换形参,将实参代人宏文本中
如果实参也是宏则展开实参
处理宏替换后的宏文本,若宏文本也包含宏则继续展开,否则完成展开。
这里有个例外,也是理解本题的重点。第一步将实参代入后,如果遇到字符“#”或“##”,即使实参是宏,也不再展开实参,而是当作文本处理。即凡宏定义里有‘#’和‘##’的地方宏参数不再展开。
首先来看
h(f(1,2))
g(f(1,2))
g(#12)
12
接下来看
g(#f(1,2))
f(1,2)
>下面这段代码的输出结果是:
>
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)
相关文章推荐
- c语言中time函数的用法 .
- 栈的实现 - C++
- oc语言第八课 内存管理二——ios学习连载13
- C++类的对象和类的指针的区别、指针和引用的区别
- c++线性存储
- VC++中操作XML(MFC、SDK)转
- C语言之文件操作02——输出文本文件中的内容显示在屏幕上
- C语言之文件操作01——打印1000以内的质数到文件
- 用链表实现id,姓名,分数的录入功能和排序功能
- 位置式PID算法的C语言代码
- 静态数组实现循环队列 c语言
- C++学习笔记——继承与派生(二)
- C语言去除字符串空格
- zz:用C语言编写Windows服务程序的五个步骤 分享到: QQ空间 新浪微博
- zz: C++后台服务程序开发模式
- iOS开发分分钟搞定C语言 —— 总结
- C++中max_element和min_element
- C++/CLI——读书笔记《Visual C++/CLI从入门到精通》 第Ⅰ部分
- C/C++经典算法精华整理(1)-求一个数的二进制类型中1(或0)的个数
- c++第一季测试题