[麦麦茶水间] 【每周分享】C语言几个特别有用的预定义宏的说明

[复制链接]
 楼主| 发表于 2025-8-7 17:08 | 显示全部楼层 |阅读模式
本帖最后由 dffzh 于 2025-8-7 17:14 编辑

#申请原创#
@21小跑堂

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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
发表于 2025-8-8 14:07 | 显示全部楼层
这些都不是C标准里的吧

点评

是的,应该算是C编译器里定义的。  发表于 2025-8-8 14:26
您需要登录后才可以回帖 登录 | 注册

本版积分规则

104

主题

1143

帖子

22

粉丝
快速回复 返回顶部 返回列表