【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
来源:互联网 发布:unity3d室内场景建模 编辑:程序博客网 时间:2024/05/17 23:22
转自:http://www.linuxidc.com/Linux/2014-06/102925.htm
#是把宏参数变为一个字符串,##是把两个宏参数连接在一起。
有一道经典的C语言问题,关于宏定义中#和##符号的使用和宏定义展开问题
程序如下:
#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;
}
答案:第一行:12 第二行:f(1,2)
说明:
1、关于符号#和##
两个符号都只能用于预处理宏扩展。不能在普通的源码中使用它们,只能在宏定义中使用。
简单的说,#是把宏参数变为一个字符串,##是把两个宏参数连接在一起。
关于这两个符号的具体意义和用法可以参见两篇文章:
#和##在宏替换中的作用 http://www.linuxidc.com/Linux/2014-06/102921.htm
C/C++ 宏中"#"和"##"的用法 http://www.linuxidc.com/Linux/2014-06/102924.htm
还有GCC帮助文档上的解释:
3.4 Stringification
3.5 Concatenation
2、关于宏展开
预处理过程的几个步骤:
1)字符集转换(如三联字符)
2)断行链接/
3)注释处理,/* comment */,被替换成空格
4)执行预处理命令,如#inlcude、#define、#pragma、#error等
5)转义字符替换
6)相邻字符串拼接
7)将预处理记号替换为词法记号
第4)步即如何展开宏函数的规则:在展开当前宏函数时,如果形参有#或##则不进行宏参数的展开,否则先展开宏参数,再展开当前宏。
宏替换顺序英文描述如下:
A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token, is replaced by the corresponding argument after all macros contained therein have been expanded.
3、总结
综合以上,对于这道题来说,第一行h(f(1,2)),由于h(a)非#或者##所以先展开其参数f(1,2),即12,所以变成h(12),然后再宏替换为g(12),再次替换为12。
第二行g(f(1,2)),宏g(a)带有#,所以里面的f(1,2)不展开,所以变成f(1,2)
类似的这种问题在《你必须知道的495个C语言问题》中出现过,在121页的“预处理功能”的问题11.19,有兴趣的朋友可以看一看。
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- 关于宏定义中#和##符号的使用和宏定义展开问题
- 宏定义中#和##符号的使用和宏定义展开问题
- C语言中宏定义"#"和"##"符号的用法
- C语言宏定义中的#和##符号
- C 语言宏定义时紧跟#和##后面的宏不能展开的问题
- c 语言中宏定义和定义全局变量的区别
- c语言宏定义中##连接符和#的使用
- C语言和C++语言中关于NULL 的定义
- 宏定义中的#和##的宏展开问题
- C语言中宏定义中的#和##
- 关于宏定义的展开
- C语言中宏定义和函数的取舍
- (搬运)如何正确获得Android内置SD卡跟外置可插拔SD卡
- IE8 未知的运行时错误(ueditor编辑器在ie8、ie7下出现JS错误的解决方法)
- Android开发必备(干货源码放送大)
- QT:moveToThread与信号与槽机制的第五个参数Qt::ConnectionType
- 记录 关于Unicode 转 UTF-8 字符编码
- 【C语言】关于宏定义中#和##符号的使用和宏定义展开问题
- ldap服务器搭建——问题整理
- 撮合系统设计调研(2)
- LINUX-网络-ifconfig
- Android中Canvas绘图详解
- Spring boot将配置属性注入到bean类中
- Android 解决dialog无法弹出输入键盘
- 微信amr格式语音转MP3
- Java回调以及线程综合应用实例