可变参数宏的原理及作用
来源:互联网 发布:js获取所有input的值 编辑:程序博客网 时间:2024/05/29 04:43
有什么作用呢?
主要是为了方便管理软件中的打印信息。我们在写代码或者修改bug时通常会将一些重要参数打印出来,方便我们debug,但是软件发行的时候通常我们不希望有这些打印,可变参数宏就可以在这里大显身手,当然也可以用分级控制(ERR、INFO/ WARNING DEBUG)的方式来管理,实现起来也不麻烦,只要在这个宏中添加判断语句就可以。
但是一般我们调试问题,不会把所有打印都打开,因为工程具有一定规模的时候,打印非常多;通常我们只打开某个文件或者模块的打印,这时可以再对应模块中添加变了或者宏来控制打印。
常用的有2种方式:
#define DEBUG_PRINT(fmt,args...) do{printf(fmt"\r", ##args);}while(0)
与
#define DEBUG_PRINT(fmt, ...) do {printf(fmt"\r", ##__VA_ARGS__);}while(0)
效果一样的, 下面就来分析一下这个原理:
1. 首先我们需要知道,可变参数宏是在C99标准中才实现的,以前没定义这个 __VA_ARGS__宏,这个宏就代表可变参数列表,在GCC中 也支持args...这种写法。
2. 关于do {...}while(0) 的用处多多,其中一个就是防止宏展开后,代码出问题。
例如, if(true) PRINTF 如果这时printf中含有2两以上代码,那么就会导致只能执行第一条。
3. ## 这个符号在宏定义中的作用是连接字符串,会忽略前后的空格, 如 A ## B 宏展开后为 AB
4. fmt "\r" 这里\r 是为了兼容windows下换行符。
fmt 就是前面的第一个参数 ,是一个字符串里面可以包含格式控制符, 这里宏展开后 fmt 会直接展开成printf的第一个参数。然后在printf函数中这个字符串和“\r”会自动连接成一个字符串。(这个字符串连接功能的具体实现不知道是不是在printf函数中)
5. 关于宏展开我们可以再编译时指定 -E参数 就可以查看到宏展开后的代码。
如: gcc -E input.c -o ouput.i
查看ouput.i 就可以发现宏展开后的是什么样子
举个例子:
/**********************************sum.c********************************************/
#include <stdio.h>
#ifdef DEBUG
#define DEBUG_PRINT(fmt,args...) do{printf(fmt"\r", ##args);}while(0)
#else
#define DEBUG_PRINT(fmt,args...) do{/*printf(fmt"\r", ##args)*/;}while(0)
#endif
int sum(int a, int b);
int main()
{
int result = 0;
result = sum(1, 2);
printf("result = %d\n", result);
return 0;
}
int sum(int a, int b)
{
DEBUG_PRINT("a = %d, b = %d\n", a, b);
return a+b;
}
/**********************************end********************************************/
当这个文件有几百行几千行的时候里面可以有很多打印信息,我们可以通过DEBUG宏来控制打印信息是否显示出来。
这样当关闭DEBUG宏时也不会有警告信息。
- 可变参数宏的原理及作用
- 可变参数及可变参数宏的使用
- 可变参数及可变参数宏的使用
- 可变参数及可变参数宏的使用
- 可变参数及可变参数宏的使用
- 可变长度函数参数的原理及使用
- 可变参数函数的原理
- va_list可变参数原理及vsprintf函数
- 可变参数列表原理及应用
- 可变参数列表用法及原理
- 可变参数的宏
- 可变参数的宏
- 可变参数的宏
- 可变参数的函数的原理
- 可变参数的原理(转)
- C语言可变参数的原理
- C/C++中可变参数的原理
- C/C++中可变参数的原理
- 第十一周项目1(2)-二叉树构造算法的验证
- Java网络爬虫crawler4j学习笔记<14> BasicAuthInfo类
- Android 6.0 SD卡路径获取
- 开发中遇到的错误
- 好好学习大数据
- 可变参数宏的原理及作用
- IOS XIB 实现比例边距&等分
- 第十一周 项目-验证算法(2)-二叉树构造算法的验证
- iOS10 UI设计基础教程
- SurfaceView加载屏幕闪烁、图层不显示的一些解决办法
- 第二章:Dubbo整合maven+spring+springmvc+mybatis之服务提供者搭建
- 第十一周项目1哈夫曼编码的算法验证
- Wireshark图解教程(简介、抓包、过滤器)
- div里面的li一行显示,ul居中