在编写项目时,我们通常需要日志输出来帮助我们追踪程序执行的内容,以便在出现BUG时较为方便的复现,并在调试完成后快速的关闭过于详细的LOG输出,避免干扰使用中的体验,在函数中一个一个的增加printf函数相比之下较为不便,并且也不便于完成调试后的注释
为了解决这个问题,我们可以利用C语言中的宏定义来快速的构建一个自定义的调试功能,在能够输出详细信息的同时还可以一键开关
正文编译器内置宏:
编译器内置了一些宏定义,这些宏定义不仅可以帮助我们完成跨平台的源码编写,也可以巧妙地帮我们输出非常有用的调试信息
ANSI C标准中有几个标准预定义宏:
- LINE:等同于当前源代码中所在位置的行号;
- FILE:等同于当前源文件名;
- DATE:在源文件中插入编译时的日期
- TIME:在源文件中插入编译时的时间;
定义用来打log的语句
使用以上这几个宏定义,可以简单的构建一个打LOG语句,其具体实现方法如下
#include "stdio.h"
// 这里选择__DEBUG__作为开关,注释掉下面这一行,则可以直接关闭程序中的DEBUG输出
#define __DEBUG__
#ifdef __DEBUG__
// 如果对__DEBUG__进行定义,则将对DEBUG(format,...)中的内容按照printf的方式进行输出
#define DEBUG(format,...) printf("File: %srnFun: %srnLine: %05drn"format"n", __FILE__, __func__, __LINE__, ##__VA_ARGS__)
// 不知道##__VA_ARGS__的含义的话可以看这个:https://zhuanlan.zhihu.com/p/410584465
#else
// 如果没有对__DEBUG__进行定义,则DEBUG(format,...)会被替换为空,所以DEBUG语句将不会输出
#define DEBUG(format,...)
#endif
通过以上代码,我们就定义出了一个可以一键开关,并且对DEBUG()语句所在位置进行快速输出调试的语句,语句被执行时就会自动打印当前所在的文件、函数与在源代码中的行数,同时括号里的内容会作为自定义语句进行输出,下面我们将这个语句放在代码用测试一下
#include "stdio.h"
// 这里选择__DEBUG__作为开关,注释掉下面这一行,则可以直接关闭程序中的DEBUG输出
#define __DEBUG__
#ifdef __DEBUG__
// 如果对__DEBUG__进行定义,则将对DEBUG(format,...)中的内容按照printf的方式进行输出
#define DEBUG(format,...) printf("File: %srnFun: %srnLine: %05drn"format"n", __FILE__, __func__, __LINE__, ##__VA_ARGS__)
#else
// 如果没有对__DEBUG__进行定义,则DEBUG(format,...)会被替换为空,所以DEBUG语句将不会输出
#define DEBUG(format,...)
#endif
void fun_name()
{
char str[]="Hello Worldrn";
DEBUG("[DEBUG LOG]: %srn",str); //输出自定义内容[DEBUG LOG]: Hello World
}
int main()
{
fun_name();
printf("compile data:%srncompile time:%srn", __DATE__, __TIME__);
return 0;
}
测试效果
开启调试功能
如果想要开启调试功能,则不需要改动代码,直接运行后的效果如下图所示
注意:File,compile time,compile data与源代码所在的地址,编译的时间,编译的日期有关,结果是会存在差异的
注释#define __DEBUG__即可关闭调试语句的输出,使得DEBUG()时效,此时运行效果如下


![[C语言] 在单片机的嵌入式开发中使用宏定义一键开关日志输出/打log调试 [C语言] 在单片机的嵌入式开发中使用宏定义一键开关日志输出/打log调试](http://www.mshxw.com/aiimages/31/1015395.png)
