云计算百科
云计算领域专业知识百科平台

模块化编程——`.h`文件中的条件编译的写法详解

问题来源

  • 例如野火STM32F407霸天虎V2的点亮LED灯的项目为例。
    下面是bsp_led.h文件

#ifndef _BSP_LED_H_
#define _BSP_LED_H_

#include "stm32f4xx.h"
void LED_GPIO_Config(void);

#endif

  • 各种的视频教程都直接告诉你结论,这个条件编译的写法可以预防重复编译,有些人可能一下就明白为什么,而有些人却想不明白它是如何做到的。
  • 对于刚开始学习单片机的人来说,这确实难以理解,主要是因为开始的时候代码量并没有很大,重复编译的问题还不太明显;但是对于久经沙场的老手,长期接触代码量很大的项目,就很清楚为什么要预防重复编译。
  • 下面我会假设一个不算小也不算大的项目例子来说明,这种条件编译的写法是如何预防重复编译的。

重复包含led.h的场景例子

假设main.c里的内容是这样的:

#include "bsp_led.h"
#include "bsp_key.h"
│ └── #include "bsp_led.h" ← 间接又包含了led.h!
#include "bsp_tim.h"
└── #include "bsp_led.h" ← 再次包含!

  • 你应该知道:#include预处理命令,其本质就是在编译之前进行文本替换。

假设这些.h文件没有用条件编译

  • 我们假设没有写条件编译,并且各个.h文件的内容如下:
    bsp_led.h:

(led的代码)

bsp_key.h

#include "bsp_led.h"
(key的代码)

bsp_tim.h

#include "bsp_led.h"
(tim的代码)

那么通过#include进行文本替换后的main就是这样的:

(led的代码)

(led的代码)
(key的代码)

(led的代码)
(tim的代码)

这时我们发现bsp_led.h的内容被重复包含了。

当.h文件使用条件编译后

  • 如果我们加上条件编译:
    bsp_led.h:

#ifndef _BSP_LED_H_
#define _BSP_LED_H_

(led的代码)

#endif

bsp_key.h

#ifndef _BSP_KEY_H_
#define _BSP_KEY_H_

#include "bsp_led.h"
(key的代码)

#endif

bsp_tim.h

#ifndef _BSP_TIM_H_
#define _BSP_TIM_H_

#include "bsp_led.h"
(tim的代码)

#endif

这时通过#include进行文本替换后的main就是这样的:

/* 这里是bsp_led.h */
#ifndef _BSP_LED_H_
#define _BSP_LED_H_

(led的代码)

#endif
/*—————-*/

/* 这里是bsp_key.h */
#ifndef _BSP_KEY_H_
#define _BSP_KEY_H_

/* 这里包含了bsp_led.h */
#ifndef _BSP_LED_H_
#define _BSP_LED_H_

(led的代码)

#endif
/*——————–*/

(key的代码)

#endif
/*—————-*/

/* 这里是bsp_tim.h */
#ifndef _BSP_TIM_H_
#define _BSP_TIM_H_

/* 这里包含了bsp_led.h */
#ifndef _BSP_LED_H_
#define _BSP_LED_H_

(led的代码)

#endif
/*——————–*/

(tim的代码)

#endif
/*—————-*/

  • 这里大家可以自己捋一下预编译后剩下什么(预编译后宏定义会被删除:#ifndef #define #endif),其实到这里再按照上面的代码自己顺一下就豁然开朗了。
  • 将你自己顺过来的有效代码和下面的对一下,看看有没有错。
  • 最后剩下的有效代码如下:

(led的代码)
(key的代码)
(tim的代码)


到这里如果你认真阅读并思考后一定已经解决了你想问的问题了。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 模块化编程——`.h`文件中的条件编译的写法详解
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!