dffzh 发表于 2025-8-7 17:08

【每周分享】C语言几个特别有用的预定义宏的说明

本帖最后由 dffzh 于 2025-8-7 17:14 编辑

#申请原创#
@21小跑堂

在嵌入式C开发中,其实有几个特别有用的预定义宏,可以用来进行软件版本管控,日志信息打印和问题排查分析等,这几个宏为编译器定义的,并非C语言标准库固有的关键字,函数或宏定义,本文章要介绍的预定义宏主要包括下面4个:__DATE__:为一个字符串常量,主要用于获取当前日期,即可以用来表示程序编译的日期,日期格式为:月份英文缩写 两位数日期 四位数年份;简单用法为:printf("app build date: %s \r\n", __DATE__); __TIME__:为一个字符串常量,主要用于获取当前时间,即可以用来表示程序编译的时间,为24小时制,时间格式为:小时:分钟:秒钟;简单用法为:printf("app build time: %s \r\n", __TIME__); 这里需要注意的是,上面两个宏反映的是程序编译时间,而不是程序运行时间;这意味着每次重新编译程序时,这些宏的值都会更新,但在程序运行期间,它们的值是保持不变的。__LINE__:为一个整型常量,主要用来表示当前代码所在的行号,即在文件中的第几行,常用于调试,日志记录等,可以帮助开发者更快地定位代码位置。简单用法为:printf("当前行号: %d \r\n", __LINE__);__FILE__:为一个字符串常量,主要用来表示当前源文件的文件名信息(相对路径),常用于调试信息,日志记录及错误报告中。简单用法为:printf("当前文件: %s \r\n", __FILE__);以上描述的4个预定义宏,几乎所有的用于MCU开发的C编译器都支持,包括:
GCC(如ARM GCC);IAREmbedded Workbench;KeilMDK-ARM;MicrochipXC系列编译器。接下来我们通过实际代码和运行测试给大家展示一下代码结果。我们先来看看最简单的用法,即逐个打印出来这4个宏的信息,main.c里面的代码如下:printf("app build date: %s\r\n", __DATE__);
printf("app build time: %s\r\n", __TIME__);
printf("app current line: %d\r\n", __LINE__); //此代码在main.c的第124行
printf("app current file: %s\r\n\r\n", __FILE__);
编译程序并运行后通过串口查看执行结果,如下图所示:如果把日期和时间结合起来使用,可以用如下代码:printf("app build date: %s %s\r\n", __TIME__, __DATE__);
printf("app current line: %d\r\n", __LINE__);
printf("app current file: %s\r\n\r\n", __FILE__);执行结果如下图所示:程序编译日期和时间往往会被加在初始化代码里,与固件版本放在一起,每次上电后执行一次输出,即可通过串口等终端掌握当前固件的相关信息,便于软件问题追踪和固件版本管控,参考代码如下所示:printf("app version: V%d.%d.%d, %s %s\r\n",LC02_VERSION_MAJOR,LC02_VERSION_MAIN,LC02_VERSION_PATCH,__TIME__, __DATE__);执行结果如下图所示:另外,在实际代码开发和调试时,__FILE__和__LINE也经常被结合使用,以达到快速定位代码异常位置的目的,参考代码如下:printf("%s:%d\r\n", __FILE__, __LINE__);在调试信息太多时,如果你想将调试信息分类,也可以给调试信息分级别,比如加上INFO,DEBUG和ERROR等标签都可以,参考代码如下:printf(" %s:%d\r\n", __FILE__, __LINE__);
printf(" %s:%d\r\n", __FILE__, __LINE__);
printf(" %s:%d\r\n", __FILE__, __LINE__);
这个时候,为了更好地管理调试信息,可以增加一个宏定义,参考代码如下:#define LOG_ERROR(message)   printf(" %s:%d - %s\n", __FILE__, __LINE__, message)message即为需要的自定义的错误打印信息。比如需要输出传感器数据异常错误,你就可以编写如下代码:LOG_ERROR("sensor data error, please check and retry!");可以参考下面的代码进行使用,当然可以扩展的更好:#define LOG_INFO(message)printf(" %s:%d - %s\n", __FILE__, __LINE__, message)
#define LOG_DEBUG(message) printf(" %s:%d - %s\n", __FILE__, __LINE__, message)
#define LOG_ERROR(message) printf(" %s:%d - %s\n", __FILE__, __LINE__, message)
执行结果如下图所示:在有些串口助手软件里,类似这种error信息,都会直接用不一样的颜色标注出来,一目了然,一看就知道是出现运行错误信息了,我用的串口助手是MobaXterm。综上所述,在程序开发和问题调试时,如果你能灵活使用这4种预定义宏,则可以显著提高调试效率。

玛尼玛尼哄 发表于 2025-8-8 14:07

这些都不是C标准里的吧

xionghaoyun 发表于 2025-8-10 01:21

#define 才是吧

21mengnan 发表于 2025-8-14 10:11

这些知识很重要,又很基础。

dffzh 发表于 2025-8-14 17:20

21mengnan 发表于 2025-8-14 10:11
这些知识很重要,又很基础。

是的呢,考验嵌入式开发功底的。

lansebuluo 发表于 2025-9-10 08:20

把这个添加到程序中,设置软件版本,不用每次自己手动更改了

dffzh 发表于 2025-9-16 08:54

本帖最后由 dffzh 于 2025-9-16 08:55 编辑

@21小跑堂 管理员,你好,求原创审核哦!
页: [1]
查看完整版本: 【每周分享】C语言几个特别有用的预定义宏的说明