0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ANSIC几种特殊的标准定义 (__FILE__、__LINE__、__STDC__···)

黄工的嵌入式技术圈 来源:黄工的嵌入式技术圈 2020-03-20 09:46 次阅读

Ⅰ写在前面

为方便大家阅读,本文内容已经整理成PDF文件:

http://pan.baidu.com/s/1gfHygyn

对于我们大部分使用单片机进行裸机开发的朋友来说,可能很少有人在程序中许多关键的地方打印一些关键信息

有较大系统开发,或复杂系统开发经验的朋友一般都会在程序中输出很多调试信息,如在UCOSfreeRTOSLinux等系统开发调试时打印许多关键信息。

1.我们在使用STM32库开发时,在stm32fxxx_conf.h文件下会发现如下这么一条语句:

#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))

这条语句,对于使用寄存器,开发简单且不大程序的朋友而言,可能他觉得用处不大,它可能就觉得很占资源,且耗时。

其实不然,ST这么设计是有他一定的道理的,对于开发大型、复杂系统的朋友而言,这条语句其实用处很大。每次,程序运行错误之后,它会打印程序代码指定的位置,方便我们在庞大的程序中很快找到错误的位置。

2.我们的系统会随着时间的推移,不断升级更新,也就是需要提交很多版本的可执行文件(hex、bin等)。但是,产品后期使用中,我们对某些设备进行了升级,可能忽略了一些设备,也就是有些设备没有升级,如果出现故障,我们怎样才能很快找到是哪一个版本的软件出现故障呢?

这里就需要我们在程序中添加一些关于版本的信息,我们最基础的就是Vx.x.x.x等这种信息,但对于大型系统而言,这种信息是不够的,还需要更多,比如:编译日期,时间,编译环境的版本等。

Ⅱ几种特殊标准定义

上面说了这么多,就是需要让大家知道,这些特殊标准定义的用途。上面说的只是简单的举例,其实他们的用途还很广泛,掌握了基础之后相信你们都会知道它们更多比较实用的意义。言归正传,下面讲述这些基础的知识。

本文主要讲述下面几个标准定义:

__LINE__:正在编译文件的行号

__FILE__:正在编译文件的文件名

__DATE__:编译时刻的日期字符串 如“Jun 17 2017”

__TIME__:编译时刻的时间字符串 如”1000“

__STDC__:判断该文件是不是标准C程序

1.__FILE__编译文件名称

File中文意思即文件,这里的意思主要是指:正在编译文件对应正在编译文件的路径和文件的名称。

Keil版本对应的路径是相对于工程文件而言的路径,IAR版本路径是相对Windows路径。

比如下面提供源代码工程:

char BuildFile[] = __FILE__;

printf("编译文件路径:%s\n", BuildFile);

Keil:

编译文件路径:App\main.c

IAR:

编译文件路径:C:\Users\Administrator\Desktop\STM32F417ZG(IAR)_ANSIC几种特殊的标准定义\App\main.c

2.__LINE__编译文件行号

上面说的是编译的文件名,是一个字符串,而这里说的是行号,是一个整型变量,这是这两者的区别,所以在我提供工程中可以看到的源代码:

char BuildLine = __LINE__;

printf("编译代码所在行:%d\n", BuildLine);

可以看不是数组的字符串,打印信息:

编译代码所在行:44

一般情况下,__FILE__是和__LINE__结合一起使用,用于打印我们代码信息,方便快速定位代码位置。

3.__DATE__编译日期

__DATE__日期,需要注意的是:这个日期是你在编译时Windows系统的日期,如果对应那部分代码之前编译好了,后面没有编译,这个日期还是之前的日期,而不是后面编译的日期。因此,如果这里用于定版本,就需要在定版本时对工程进行全部重新编译,它才会更新至你最后编译的日期。

代码:

char BuildDate[] = __DATE__;

printf("编译日期:%s\n", BuildDate);

输出结果:

编译日期:Jun 17 2017

4.__TIME__编译时间

这个和__DATE__一样的原理,编译时的时间,也是一个字符串。

再次提醒:用于定版本:需要重新编译,这样才是最后一次编译时间。

代码:

char BuildTime[] = __TIME__;

printf("编译时间:%s\n", BuildTime);

输出结果

编译时间:1115

5.__STDC__标准C代码

这个标准在我们单片机及嵌入式编程中运用的比较少,当要求程序严格遵循ANSIC标准时该标识符被赋值为1,主要是判断我们的程序文件是不是标准C程序。

#ifdef __STDC__

printf("标准C代码文件\n");

#else

printf("非标准C代码文件\n");

#endif

Ⅲ源代码分析与下载

为了方便大家学习,本文提供的源代码比较基础和简单,也方便理论结合实际学习,仅供参考。

我们在之前新建好的Demo工程上添加了如下部分代码:

char BuildLine = __LINE__;

char BuildFile[] = __FILE__;

char BuildDate[] = __DATE__;

char BuildTime[] = __TIME__;

printf("编译文件路径:%s\n", BuildFile);

printf("编译代码所在行:%d\n", BuildLine);

printf("编译日期:%s\n", BuildDate);

printf("编译时间:%s\n", BuildTime);

#ifdef __STDC__

printf("标准C代码文件\n");

#else

printf("非标准C代码文件\n");

#endif

Keil版本输出结果:

编译文件路径:App\main.c

编译代码所在行:44

编译日期:Jun 17 2017

编译时间:1115

标准C代码文件

IAR版本输出结果:

编译文件路径:C:\Users\Administrator\Desktop\STM32F417ZG(IAR)_ANSIC几种特殊的标准定义\App\main.c

编译代码所在行:44

编译日期:Jun 17 2017

编译时间:1100

标准C代码文件

源代码工程(STM32F417ZG_ANSIC几种特殊的标准定义)下载地址:

http://pan.baidu.com/s/1hskScba

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6001

    文章

    43973

    浏览量

    620821
  • 寄存器
    +关注

    关注

    30

    文章

    5028

    浏览量

    117718
  • ANSIC
    +关注

    关注

    0

    文章

    6

    浏览量

    8615
收藏 人收藏

    评论

    相关推荐

    如何用cubemx做lin通信?

    ; if (HAL_LIN_Init( huart3, UART_LINBREAKDETECTLENGTH_11B) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } }
    发表于 04-26 07:44

    STM32H743 UART DMA数据发送报错的原因?

    = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init( huart4) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } void
    发表于 04-26 06:59

    虚拟串口与STM32通信遇到的疑问求解

    ; if (HAL_RCC_ClockConfig( RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { _Error_Handler(__FILE__, __LINE__
    发表于 04-24 08:29

    主循环里不断开启关闭ADC的DMA传输功能,上电有几率死机怎么解决?

    ; if (HAL_ADC_ConfigChannel( hadc1,sConfig) != HAL_OK) _Error_Handler(__FILE__, __LINE__); for(i = 0; i &
    发表于 04-23 07:20

    STM32F0 ADC多通道单次转换,最后一个通道的EOC不置位是为什么?

    = ADC_OVR_DATA_PRESERVED; if (HAL_ADC_Init( hadc) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } sConfig.Channel
    发表于 04-16 06:34

    STM32F103VET6使用定时器DMA做比较输出PWM,输出波形第一次不正确是怎么回事?

    ) { Error_Handler(__FILE__, __LINE__); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL
    发表于 03-28 07:27

    美国FCC最新标准(HAC 2019),2023年12月5日起实施

    根据美国联邦通信委员会(简称FCC)的要求,从2023年12月5日开始,手持终端设备必须符合ANSIC63.19-2019标准(也称为HAC2019标准)。根据最新发
    的头像 发表于 12-06 15:17 701次阅读
    美国FCC最新<b class='flag-5'>标准</b>(HAC 2019),2023年12月5日起实施

    LVDS电平学习笔记

    LVDS电平是根据ANSI/EIA/TIA-644定义的一种电平标准,其标准定义的相关参数如下。
    的头像 发表于 09-20 15:29 946次阅读
    LVDS电平学习笔记

    ARM-THUMB程序调用标准

    该基础标准定义了ARM和Thumb通用的机器级、仅整数调用标准和ARM的机器级浮点标准。 Thumb指令集不包括协处理器指令,没有用于Thumb的机器级浮点标准
    发表于 08-17 07:36

    K_Line-尝尝吧!

    K_Line - 尝尝吧!
    发表于 06-28 19:16 0次下载
    K_<b class='flag-5'>Line</b>-尝尝吧!

    K_Line-尝尝吧!

    K_Line - 尝尝吧!
    发表于 06-28 19:12 0次下载
    K_<b class='flag-5'>Line</b>-尝尝吧!

    Linux使用gcc编译程序的语法

    运行的函数和当前的程序行。 具体宏如下: __FILE__ 当前程序源文件 (char*) __FUNCTION__ 当前运行的函数 (char*) __LINE__ 当前的函数行 ( int
    的头像 发表于 06-22 10:51 379次阅读

    JTAG 连接器和接口

    尽管 JTAG 接口没有一种标准接头,但制造商之间已或多或少地标准化了几种接头类型。其中包括ARM JTAG 20、ARM JTAG 14、TI JTAG 14、STMicroelectronics
    的头像 发表于 06-06 10:18 3159次阅读
    JTAG 连接器和接口

    K_Line-尝尝吧!

    K_Line - 尝尝吧!
    发表于 05-11 18:52 0次下载
    K_<b class='flag-5'>Line</b>-尝尝吧!

    K_Line-尝尝吧!

    K_Line - 尝尝吧!
    发表于 05-11 18:48 0次下载
    K_<b class='flag-5'>Line</b>-尝尝吧!