商城网站设计服务删除中文wordpress
web/
2025/9/28 1:57:07/
文章来源:
商城网站设计服务,删除中文wordpress,百度站长工具后台,免费的网站管理系统宏打印函数 在我们的嵌入式开发中#xff0c;使用printf打印一些信息是一种常用的调试手段。但是#xff0c;在打印的信息量比较多的时候#xff0c;就比较难知道哪些信息在哪个函数里进行打印。特别是对于异常情况的打印#xff0c;我们需要快速定位到异常情况的位置。这时… 宏打印函数 在我们的嵌入式开发中使用printf打印一些信息是一种常用的调试手段。但是在打印的信息量比较多的时候就比较难知道哪些信息在哪个函数里进行打印。特别是对于异常情况的打印我们需要快速定位到异常情况的位置。这时候我们可以使用宏定义来封装一个宏打印函数这个宏打印函数可以显示打印信息所在的文件、行数、函数名等信息。如左右滑动查看全部代码#define DBG_PRINTF(fmt, args...) \
{\printf(File:%s Line:%d Function:%s , __FILE__, __LINE__, __FUNCTION__);\printf(fmt, ##args);\
}
使用范例可见使用方法与printf的使用方法一样而且每条打印语句开头都会打印调试信息所在的文件名、行号、函数名信息方便我们查找一些调试信息。其中__FILE__、__LINE__、__FUNCTION__这三个宏是编译器内置宏定义分别代表调试信息所在文件、行号、函数。除此之外常用的宏还有__DATE__、__TIME__分别代表当前的编译日期与时间。如DBG_PRINTF(Compile Time: %s %s\n, __DATE__, __TIME__);
第二条printf中的##符号是为了处理args不代表任何参数的情况。如DBG_PRINTF(Hello world);
当不加##符号是以上宏的第二条语句被拓展为printf(Hello world\n, );
可见多出了一个逗号这个逗号是多余的。加上##符号后以上宏的第二条语句被拓展为printf(Hello world\n);
这才是我们想要的结果。其实这些结果我们通过查看预处理文件可以清晰的知道最后需要注意的是这个DBG_PRINTF还是与printf不一样的。DBG_PRINTF宏是两条语句的组合无返回值而printf的原型是int printf (const char *__format, ...)
但是我们一般都很少使用printf的返回值所以DBG_PRINTF的用法与printf函数基本一致。打印调试宏开关 通常情况下一些打印调试信息只是在我们调试阶段需要的在程序发布阶段是不需要的。所以为了避免打印调试信息带来的资源开销我们可以把这些打印调试语句给注释掉。一种方法是逐句进行注释这是一种比较低效的方法。比较高效的方法就是添加调试宏开关利用条件编译来选择打印/不打印调试信息。比如我们可以把上面的代码改造为#define DEBUG 1 #if DEBUG#define DBG_PRINTF(fmt, args...) \{\printf(File:%s Line:%d Function:%s , __FILE__, __LINE__, __FUNCTION__);\printf(fmt, ##args);\}
#else#define DBG_PRINTF(fmt, args...)
#endif
根据DEBUG宏的值来选择对应的打印宏函数。当DEBUG的值为1时启动相关的打印调试语句DEBUG的值为0时则关闭打印调试语句。这样我们就可以很方便的通过设置DEBUG宏的值来启动与关闭我们整个工程的DBG_PRINTF打印调试信息。do{}while(0) 其实上面我们封装的打印宏DBG_PRINTF还有一点缺陷比如我们与if、else使用的时候会有这样的一种使用情况此时会报语法错误。为什么呢同样的我们可以先来看一下我们的demo代码预处理过后相应的宏代码会被转换为什么。如这里我们可以看到我们的if、else结构代码被替换为如下形式if(c)
{ /* ....... */ };
else
{ /* ....... */ };
显然出现了语法错误。if之后的大括号之后不能加分号这里的分号其实可以看做一条空语句这个空语句会把if与else给分隔开来导致else不能正确匹配到if导致语法错误。为了解决这个问题有几种方法。第一种方法是把分号去掉。代码变成第二种方法是在if之后使用DBG_PRINTF打印调试时总是加{}。代码变成以上两种方法都可以正常编译、运行了。但是我们C语言中每条语句往往以分号结尾并且总有些人习惯在if判断之后只有一条语句的情况下不加大括号而且我们创建的DBG_PRINTF宏函数的目的就是为了对标printf函数printf函数的使用加分号在任何地方的使用都是没有问题的。基于这几个原因我们有必要再对我们的DBG_PRINTF宏函数进行一个改造。下面引入do{}while(0)来对我们的DBG_PRINTF进行一个简单的改造。改造后的DBG_PRINTF宏函数如下#define DBG_PRINTF(fmt, args...) \
do\
{\printf(File:%s Line:%d Function:%s , __FILE__, __LINE__, __FUNCTION__);\printf(fmt, ##args);\
}while(0)
这里的do...while循环的循环体只执行一次与不加循环是效果一样。并且可以避免了上面的问题。预处理文件我们的宏函数实体中while(0)后面不加分号在实际调用时补上分号既符合了C语言语句分号结尾的习惯也符合了do...while的语法规则。使用do{}while(0)来封装宏函数可能会让很多初学者看着不习惯但必须承认的是这确确实实是一种很常用的方法。在STM32的HAL库中搜索while(0)在Linux源码中搜索while(0)可见在实际应用中do{}while(0)用的很多。#运算符与##运算符 这两个运算符之前也有分享过这里顺便也提一下。#号作为一个预处理运算符可以把记号转换成字符串。例如如果A是一个宏形参那么#A就是转换为字符串A的形参名。这个过程称为字符串化stringizing。以下程序演示这个过程##运算符可以把两个记号组合成一个记号。以下程序演示这个过程这个运算符用得很多。如最后以上就是本次的分享。如有错误欢迎指出谢谢本篇笔记会同步至我的个人博客https://www.lizhengnian.cn/中欢迎来访。原创不易期待您的在看、分享~ PS想加入技术群的同学加了我好友后就给我发「篮球的大肚子」这句话有可能机器人打瞌睡可以多发几次不要发与技术无关的消息或者推广。如果想获取学习资料就在公众号后台回复「1024」足够多的学习资料可以让你学习。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/83078.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!