侵权投诉

嵌入式开发中实用的宏打印函数

FPGA之家 2021-09-16 10:05 次阅读

宏打印函数在我们的嵌入式开发中,使用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

”, __DATE__, __TIME__);

第二条printf中的##符号是为了处理args不代表任何参数的情况。如:

DBG_PRINTF(“Hello world”);

当不加##符号是,以上宏的第二条语句被拓展为:

printf(“Hello world

”, );

可见,多出了一个逗号,这个逗号是多余的。

加上##符号后,以上宏的第二条语句被拓展为:

printf(“Hello world

”);

这才是我们想要的结果。其实这些结果我们通过查看预处理文件可以清晰的知道:

最后需要注意的是,这个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使用的时候,会有这样的一种使用情况:

a14a24d0-15f8-11ec-8fb8-12bb97331649.png

此时会报语法错误。为什么呢?

同样的,我们可以先来看一下我们的demo代码预处理过后,相应的宏代码会被转换为什么。如:

a158cc60-15f8-11ec-8fb8-12bb97331649.png

这里我们可以看到,我们的if、else结构代码被替换为如下形式:

if(c)

{ /* 。..。..。 */ };

else

{ /* 。..。..。 */ };

显然,出现了语法错误。if之后的大括号之后不能加分号,这里的分号其实可以看做一条空语句,这个空语句会把if与else给分隔开来,导致else不能正确匹配到if,导致语法错误。

为了解决这个问题,有几种方法。第一种方法是:把分号去掉。代码变成:

a16a0f5c-15f8-11ec-8fb8-12bb97331649.png

第二种方法是:在if之后使用DBG_PRINTF打印调试时总是加{}。代码变成:

a17d3866-15f8-11ec-8fb8-12bb97331649.png

以上两种方法都可以正常编译、运行了。

但是,我们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循环的循环体只执行一次,与不加循环是效果一样。并且,可以避免了上面的问题。预处理文件:

a188ca32-15f8-11ec-8fb8-12bb97331649.png

我们的宏函数实体中,while(0)后面不加分号,在实际调用时补上分号,既符合了C语言语句分号结尾的习惯,也符合了do.。.while的语法规则。

使用do{}while(0)来封装宏函数可能会让很多初学者看着不习惯,但必须承认的是,这确确实实是一种很常用的方法。

STM32的HAL库中搜索while(0):

a193dd8c-15f8-11ec-8fb8-12bb97331649.png

a1a28710-15f8-11ec-8fb8-12bb97331649.png

Linux源码中搜索while(0):

a1b3e5d2-15f8-11ec-8fb8-12bb97331649.png

可见,在实际应用中,do{}while(0)用的很多。

#运算符与##运算符这两个运算符之前也有分享过,这里顺便也提一下。

#号作为一个预处理运算符,可以把记号转换成字符串。

例如,如果A是一个宏形参,那么#A就是转换为字符串“A”的形参名。这个过程称为字符串化(stringizing)。以下程序演示这个过程:

##运算符可以把两个记号组合成一个记号。以下程序演示这个过程:

这个运算符用得很多。如:

责任编辑:haq

原文标题:嵌入式中几个非常实用的宏技巧~

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
分享:

评论

相关推荐

香橙派全志芯片开发板下载交叉编译工具链说明

香橙派开发板以处理器分类,包含全志H2、全志H3、全志H5、全志H6等系列,下文以全志H3芯片的开发板为例,对交叉编译工具链的...
发表于 10-21 17:35 0次 阅读
香橙派全志芯片开发板下载交叉编译工具链说明

LLC开关电源详细工作过程

LLC开关电源一般使用PFM,特定工况下使用PWM。因此本文详述了使用MOSFET,并且工作在ZVS....
发表于 10-21 16:06 4次 阅读
LLC开关电源详细工作过程

【内涵详细步骤】近期亲手DIY了一款猫咪干饭神器,真香!!

作者:刘小象您浏览的内容为涂鸦开发者平台注册用户自主发布,版权归原作者所有。 选择涂鸦智能的联网模块WBR3为主要联网...
发表于 10-21 15:18 101次 阅读

C语言堆栈程序内存的分配

    程序内存的分配       一个由C/C++编译的程序占用的内存分为以下几个部分: 栈区(s....
的头像 嵌入式ARM 发表于 10-21 14:51 61次 阅读

嵌入式软件开发常用的开发模型介绍

瀑布模型 该模型是由上至下一次性完成整个项目的开发方式。该模型一共分为6个阶段,如图所示: 在瀑布模....
的头像 嵌入式ARM 发表于 10-21 14:40 121次 阅读
嵌入式软件开发常用的开发模型介绍

如何才能学习好嵌入式

身边朋友问我如何学习嵌入式,在这个行业健康的发展。我一直未能做一个系统的回答。这里我想写篇文章,彻底....
的头像 嵌入式ARM 发表于 10-21 14:35 120次 阅读

ML规模复杂的相关基础架构

  Waze 是世界上最大的基于社区的交通和导航应用。该应用借助实时数据来帮助用户避开路上的障碍,享....
的头像 TensorFlow 发表于 10-21 14:07 90次 阅读

为什么还要学习PCB设计

明天就要开始总计30节的“嵌入式系统入门”直播课程(基于树莓派Pico + MicroPython编....
的头像 电子森林 发表于 10-21 14:01 90次 阅读

嵌入式处理器

  嵌入式处理器是嵌入式系统的核心,是控制、辅助系统运行的硬件单元。范围极其广阔,从最初的4位处理器....
发表于 10-21 13:36 9次 阅读
嵌入式处理器

嵌入式中的BSP---BSP到底是什么

转自: http://blog.chinaunix.net/uid-20788636-id-1841....
发表于 10-21 13:36 6次 阅读
嵌入式中的BSP---BSP到底是什么

嵌入式设备PHP版本升级

嵌入式设备PHP版本升级:https://notes.z-dd.net/2019/11/28/%E5....
发表于 10-21 13:36 2次 阅读
嵌入式设备PHP版本升级

嵌入式Linux开发教程:Linux常见命令(上篇)

摘要:这是对周立功编著的《嵌入式Linux开发教程》的第7期连载。本期刊载内容有关LinuxLinu....
发表于 10-21 13:36 4次 阅读
嵌入式Linux开发教程:Linux常见命令(上篇)

Duktape:一个新的小巧的超精简可嵌入式JavaScript引擎

原文链接:http://ourjs.com/detail/duktape-%E4%B8%80%E4%....
发表于 10-21 13:36 3次 阅读
Duktape:一个新的小巧的超精简可嵌入式JavaScript引擎

嵌入式linux开发视频下载

嵌入式Linux视频教程:ed2k://|file|Tiny6410%E5%9B%BD%E5%B5%....
发表于 10-21 13:21 4次 阅读
嵌入式linux开发视频下载

嵌入式linux开发视频下载

嵌入式Linux视频教程:ed2k://|file|Tiny6410%E5%9B%BD%E5%B5%....
发表于 10-21 13:21 2次 阅读
嵌入式linux开发视频下载

java 嵌入式 web 服务器

http://www.oschina.net/search?scope=project&q=....
发表于 10-21 13:21 0次 阅读
java 嵌入式 web 服务器

shc在嵌入式Linux上的使用

https://notes.z-dd.net/2020/12/13/shc%E5%9C%A8%E5%....
发表于 10-21 13:21 2次 阅读
shc在嵌入式Linux上的使用

shc在嵌入式Linux上的使用

shc在嵌入式Linux上的使用:https://notes.z-dd.net/2020/12/13....
发表于 10-21 13:21 4次 阅读
shc在嵌入式Linux上的使用

嵌入式硬件电路总结

嵌入式硬件电路总结一些常用的电源电路、外设接口电路、通讯接口电路等
发表于 10-21 13:21 5次 阅读
嵌入式硬件电路总结

嵌入式培训班有必要吗?

对于很多想要从事嵌入式相关工作的人来说,自学还是参加嵌入式培训班一直都是个大难题,难度不亚于哈姆雷特....
发表于 10-21 13:21 2次 阅读
嵌入式培训班有必要吗?

嵌入式软件未来发展趋势

虽说嵌入式未来发展一片大好,但也会有一些人很想多了解一下嵌入式,毕竟之后要学习嵌入式的话,也要多了解....
发表于 10-21 13:06 6次 阅读
嵌入式软件未来发展趋势

【测试】嵌入式软件测试VS一般软件测试

文章目录1)什么是软件测试?测试的目的:软件测试的特点:软件测试信息流:软件测试的对象:2)嵌入式软....
发表于 10-21 13:06 5次 阅读
【测试】嵌入式软件测试VS一般软件测试

嵌入式操作系统复习笔记1-------嵌入式实时操作系统基本概念

第1章 嵌入式实时操作系统基本概念1.计算机操作系统(Operating System,OS)操作....
发表于 10-21 13:06 3次 阅读
嵌入式操作系统复习笔记1-------嵌入式实时操作系统基本概念

【嵌入式实验】《嵌入式开发工具使用》

嵌入式开发工具使用一.实验目的二.实验内容三.预备知识四.实验设备及工具(包括软件调试工具)五.实验....
发表于 10-21 13:06 2次 阅读
【嵌入式实验】《嵌入式开发工具使用》

嵌入式系统

一:嵌入式系统概论嵌入式系统的特点包括:(1)系统专用性强。(2)软、硬件依赖性强。(3)系统实时性....
发表于 10-21 12:51 4次 阅读
嵌入式系统

嵌入式Linux NFS

文章目录前言服务器配置嵌入式设备挂载微信公众号前言网络文件系统(英语:Network File Sy....
发表于 10-21 12:51 2次 阅读
嵌入式Linux NFS

嵌入式人工智能-简要了解

嵌入式人工智能-简要了解OPEN AI LAB嵌入式人工智能开发套件(EAIDK)AIoTOPEN ....
发表于 10-21 12:51 14次 阅读
嵌入式人工智能-简要了解

怎样入门嵌入式嵌入式未来的发展方向

@[TOC]很多工程师要往嵌入式方向发展,特别是ARM得到应用后,这个趋势更是有增无减,但你真的知道....
发表于 10-21 12:51 3次 阅读
怎样入门嵌入式嵌入式未来的发展方向

小白找工作:嵌入式工程师(从单片机到嵌入式,我该投哪个岗位)

小白找工作:嵌入式工程师前言从单片机到嵌入式,我该投哪个岗位前言好久没有写博客了,这段时间主要是去做....
发表于 10-21 12:51 13次 阅读
小白找工作:嵌入式工程师(从单片机到嵌入式,我该投哪个岗位)

初识ARM嵌入式系统

ARM嵌入式系统的基本结构和常见的ARM微处理器ARM被称为嵌入式微处理器核。ARM嵌入式系统由3部....
发表于 10-21 12:51 6次 阅读
初识ARM嵌入式系统

嵌入式系统开发的基础知识

1.嵌入式系统的特点、分类、发展与应用,熟悉嵌入式系统的逻辑组成。(1)特点:专用性隐蔽性 (嵌入....
发表于 10-21 12:36 3次 阅读
嵌入式系统开发的基础知识

嵌入式编程和PC编程究竟有何区别?

在中国,嵌入式编程的朋友很少是正儿八经从计算机专业毕业的,都是从自动控制啊,电子相关的专业毕业的。这....
发表于 10-21 12:36 2次 阅读
嵌入式编程和PC编程究竟有何区别?

嵌入式项目 lua 的一些简要说明

lua简介,易于与CC++相互调用,执行效率高。嵌入式项目lua移植上难度不大,打包进项目,实现pr....
发表于 10-21 12:36 5次 阅读
嵌入式项目 lua 的一些简要说明

什么是嵌入式人工智能,它的实际应用

什么是嵌入式人工智能,它的实际应用百度大脑、语音搜索、图像、广告跟搜索排序及自动驾驶,用一句简单的话....
发表于 10-21 12:36 4次 阅读
什么是嵌入式人工智能,它的实际应用

移动机器人嵌入式系统详细篇

接触了移动机器人这么久,我觉得应该写点什么东西,分享一下最基础的自己关于移动机器人的理解,也作为笔记....
发表于 10-21 12:36 2次 阅读
移动机器人嵌入式系统详细篇

嵌入式软件工程师成长方向的思考

最近有点空闲,总结下嵌入式工程师所需要掌握的技能,及成长方向。主体知识:C语言、数据结构 + 算法、....
发表于 10-21 12:36 7次 阅读
嵌入式软件工程师成长方向的思考

嵌入式linux根文件系统损坏恢复方法

昨晚在对开发板的文件进行复制操作时遇到卡死,强制重启之后发现进不了命令行模式,输入回车键一直提示:c....
发表于 10-21 12:36 0次 阅读
嵌入式linux根文件系统损坏恢复方法

嵌入式linux的开发流程以及linux应用层内容

嵌入式linux开发流程:1.搭建前期的开发环境,例如搭建linux主机环境,交叉编译器的安装,还有....
发表于 10-21 12:36 2次 阅读
嵌入式linux的开发流程以及linux应用层内容

单片机和嵌入式哪个好?单片机会被嵌入式取代吗?

很多初学者都搞不清楚单片机和嵌入式的区别。今天就和大家来聊一聊这个话题。嵌入式和单片机,我喜欢用老爸....
发表于 10-21 12:21 9次 阅读
单片机和嵌入式哪个好?单片机会被嵌入式取代吗?

2018软考中级嵌入式系统设计师复习思路

历程结果八月底九月初报的名,10月初在国庆时才开始复习,11月11号开考,复习了40多天。在12月1....
发表于 10-21 12:21 3次 阅读
2018软考中级嵌入式系统设计师复习思路

嵌入式软件开发环境

嵌入式软件开发环境1 简介嵌入式软件定义嵌入式系统构成2 环境搭建2.1 Qt2.2 CLion2.....
发表于 10-21 12:21 6次 阅读
嵌入式软件开发环境

嵌入式项目基本架构

嵌入式项目基本架构大型项目体系架构大型项目由三大部分构成:分别是嵌入式终端、上位机、云服务器,如下图....
发表于 10-21 12:21 5次 阅读
嵌入式项目基本架构

嵌入式系统学习---------2.嵌入式系统设计过程

一、 系统需求分析我们在做嵌入式设计的时候,首先我们要知道要干什么、我们要实现什么,也就是要实现的目....
发表于 10-21 12:21 3次 阅读
嵌入式系统学习---------2.嵌入式系统设计过程

嵌入式设备web服务器比较

现在在嵌入式设备中所使用的web服务器主要有:boa、thttpd、mini_httpd、shttp....
发表于 10-21 12:21 2次 阅读
嵌入式设备web服务器比较

嵌入式系统设计课程笔记整理1

一.目标1、了解嵌入式技术;2、掌握嵌入式Linux操作的使用;(命令)(80%以上的开发平台都是L....
发表于 10-21 12:21 3次 阅读
嵌入式系统设计课程笔记整理1

嵌入式知识点

嵌入式知识点复习一1、 嵌入式系统的一般组成结构2、嵌入式硬件系统的结构(1)嵌入式处理器+外围硬件....
发表于 10-21 12:06 5次 阅读
嵌入式知识点

嵌入式PWM驱动蜂鸣器实验

一、实验目的掌握PWM和蜂鸣器工作原理,利用PWM驱动蜂鸣器二、实验环境1.PC微机。2.ubunt....
发表于 10-21 12:06 4次 阅读
嵌入式PWM驱动蜂鸣器实验

嵌入式Tomcat示例

嵌入式Web服务器不使用jetty,太麻烦了。配置也不熟悉。代码嵌入式Tomcat示例参考资料嵌入式....
发表于 10-21 12:06 4次 阅读
嵌入式Tomcat示例

树莓派1:嵌入式开发概述

嵌入式开发概述1.嵌入式硬件选型:嵌入式即嵌入式系统,IEEE对其定义是用于控制,监视或者辅助操作机....
发表于 10-21 12:06 8次 阅读
树莓派1:嵌入式开发概述

简单谈谈STM32(一) - 走近嵌入式

新系列准备起航,聊聊入门的那些“坑”,聊聊我们应该怎么走近嵌入式这个陌生而又熟悉的方向,让我们从入门....
发表于 10-21 12:06 5次 阅读
简单谈谈STM32(一) - 走近嵌入式

嵌入式系统开发入门

嵌入式系统开发项目1-Hello world1、创建STM32项目2、选择型号3、配置项目名称4、项....
发表于 10-21 12:06 2次 阅读
嵌入式系统开发入门

嵌入式架构到底有多重要?看完惊呆了

嵌入式架构有多重要?要做到嵌入式应用的代码逻辑清晰,且避免重复的造轮子,没有好的应用架构怎么行?如果....
发表于 10-21 12:06 2次 阅读
嵌入式架构到底有多重要?看完惊呆了

嵌入式Linux开发的流程是怎样的呢

单片机和Linux的区别在哪? 嵌入式Linux开发的流程是怎样的呢? ...
发表于 10-21 09:30 0次 阅读

从存储器哪一个位置开始读取代码呢

代码是从哪里开始运行的? 从存储器哪一个位置开始读取代码呢?...
发表于 10-21 09:11 0次 阅读

串口通信的相关代码学习

怎样去编写一种简单的串口通信代码呢? 什么是SBUF? ...
发表于 10-21 09:10 0次 阅读

如何对STM32H747 / STM32H745进行测试

STM32H747/757系列产品有哪些性能? 如何对STM32H747 / STM32H745进行测试? ...
发表于 10-21 08:24 0次 阅读

怎样用最新版的MDK530去编译原来的代码呢

怎样用最新版的MDK530去编译原来的代码呢? MDK530编译为什么会出现ARM版本不符的问题? ...
发表于 10-21 07:26 0次 阅读

在嵌入式中如何区别核心板?

发表于 10-20 11:11 0次 阅读

单片机和嵌入式的区别在哪

什么是嵌入式?单片机和嵌入式的区别在哪?
发表于 10-20 07:36 0次 阅读

怎样去操作基于STM32F407 HAL库的Flash编程呢

怎样去操作基于STM32F407 HAL库的Flash编程呢? flash的写入操作是怎样的? ...
发表于 10-20 06:05 0次 阅读