这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » 头文件中的static_inline函数

共3条 1/1 1 跳转至

头文件中的static_inline函数

院士
2026-08-10 15:26:17     打赏

头文件中的static inline函数

/**
  * @brief  Enable AHB1 peripherals clock.
  * @rmtoll AHBENR       DMA1EN        LL_AHB1_GRP1_EnableClock\n
  *         AHBENR       FLASHEN       LL_AHB1_GRP1_EnableClock\n
  *         AHBENR       CRCEN         LL_AHB1_GRP1_EnableClock
  * @param  Periphs This parameter can be a combination of the following values:
  *         @arg @ref LL_AHB1_GRP1_PERIPH_DMA1
  *         @arg @ref LL_AHB1_GRP1_PERIPH_FLASH
  *         @arg @ref LL_AHB1_GRP1_PERIPH_CRC
  * @retval None
  */
__STATIC_INLINE void LL_AHB1_GRP1_EnableClock(uint32_t Periphs)
{
  __IO uint32_t tmpreg;
  SET_BIT(RCC->AHBENR, Periphs);
  /* Delay after an RCC peripheral clock enabling */
  tmpreg = READ_BIT(RCC->AHBENR, Periphs);
  (void)tmpreg;
}

在阅读STM32官方示例代码(如开头所示)时,经常可以在HAL函数库的.h头文件中看到static inline开关的函数。为什么要使用static inline定义函数?它这样定义的方式又是在解决什么问题?在上C语言课程时,老师讲过,要将函数实现放在.c的文件中,而仅在.h头文件中做外部链接声明,以供外部.c文件引用。这时两者冲突了!是老师教的不对,还是ST官方代码有问题?让我们一点一点分析来看。

inline关键字修饰函数

inline关键字的作用是向编译器发出的建议,希望将函数体直接展开到调用处,以消除函数调用的开销(如压栈、跳转、返回等指令)。那为什么又必须在头文件中定义呢?

  • 编译器在进行编译时,是以单个 .c 文件为单位进行的。如果函数声明在头文件,而实现在另一个 .c 文件中,当前编译单元看不到函数体,就无法进行内联展开,只能生成普通的函数调用指令。

  • 只有将函数定义(实现)放在头文件中,所有包含该头文件的源文件才能在编译时看到函数体,编译器才有机会将其内联展开。

static关键字修饰函数

添加static关键字主要是为了避免链接时”多重定义“错误。

如果在头文件中定义一个普通函数(未添加static声明),当多个 .c 源文件包含该头文件时,每个 .c文件 都会生成一份该函数的目标代码。在链接阶段,链接器会发现多个同名符号,从而报错“多重定义”(Multiple Definition Error)。而static关键字赋予函数‌内部链接(Internal Linkage)‌属性。这意味着该函数仅对当前编译单元(即当前的 .c 文件及其包含的头文件)可见。详细点说,就是: 当多个 .c 文件包含含有 static inline 函数的头文件时,每个 .c 文件都会拥有该函数的一个独立私有副本。 由于这些副本彼此不可见,链接器不会认为它们是冲突的重复定义,从而顺利链接。

static与inline组合

inline关键字仅仅是建议编译器做内联处理,而加上static后,语义变得明确且稳健:‌“这个函数是每个文件私有的,并且建议内联”‌。即使编译器决定不内联(例如优化级别低或函数过大),它也会在每个使用该函数的 .o 文件中生成一个静态函数副本,保证程序能正确运行且无链接错误。

static inline的适用条件

上面的描述已经清晰表明,每个.c文件在编译的时候都会将该生成一个静态函数副本,而不是传统函数的描述符,而这也就导致了代码膨胀的问题。即,如果该函数未被内联且被频繁引用,或者头文件被大量源文件包含,会导致最终生成的bin文件体积极具增大。

static inline的适用条件:

  • 此模式仅适用于短小、高频调用的工具函数,比如ST示例代码里面的寄存器操作;

  • 替代部分宏定义的安全方案。宏只是文本替换,容易引发类型错误,也不方便单步跟踪调试;

总结

在 C 语言头文件中使用 static inline定义函数,主要是为了解决‌代码复用‌、‌性能优化‌与‌链接冲突‌三者之间的矛盾。这是一种在嵌入式开发、操作系统内核(如 Linux Kernel)及高性能库中非常常见的最佳实践。

老师课本所教知识没有错误,课本知识具有普适性,而大厂的代码是在特定需求,特定环境下的优化下的专门处理。是知识应用的一种升华。

通过源代码学习知识,关注我!我是你们的老朋友jobs。




关键词: static     inline    

助工
2026-08-11 10:57:14     打赏
2楼

明白了。感觉大部分寄存器的操作都可以,或者应该写到头文件,并使用static inline来声明


工程师
2026-08-11 11:07:04     打赏
3楼

学习了

我看有的源代码,他们就是使用宏定义来实现。

确实无法调试


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]