关于头文件中的 static inline函数
头文件中常见static inline函数,于是思考有可能遇到的问题,如头文件经常会被包含会不会产生很多副本?网上说法不一。于是自己验证。经过arm-none-eabi-gcc下测试后得出结论。
inline 关键字实际上仅是建议内联并不强制内联,gcc中O0优化时是不内联的,即使是O2以上,如果该函数被作为函数指针赋值,那么他也不会内联,也必须产生函数实体,以获得该函数地址。经测试c文件中的仅inline函数即使Os优化也不内联,因为没有static,编译认他是全局的,因此像普通函数一样编译了,本c文件也一样通过 bl inline_func 这样的方式调用,不像网上别人说的,本c会内联,其他c文件则通过bl inline_func 方式。加入static 后则内联了。(Os优化等级测试)
所以在头文件中用inline时务必加入static,否则当inline不内联时就和普通函数在头文件中定义一样,当多个c文件包含时就会重定义。所以加入static代码健壮性高,如果都内联了实际效果上是一样的。(gcc下验证过O0级别includes.h中仅定义inline的函数,编译失败,Os编译成功)
为什么要在头文件中定义函数呢?
虽然知道了头文件中用inline函数时要加入static,但是为什么要在头文件中定义函数呢?
一些简单的封装接口函数,如 open() { vfs_open() } 仅仅是为了封装一个接口,我们不希望耗费一次函数调用的时间,解决方法一是宏,但是作为接口,宏不够清晰。那选择inline,但是如果在c文件中写
main.c
inline void open(void)
{
vfs_open();
头文件加声明,外部要使用则不会内联的,因为编译器有个原则,以c文件为单位进行逐个编译obj,每个c文件的编译是独立的,该c文件用到的外部函数都在编译时预留一个符号,只有等到所有obj生成后链接时才给这些符号地址(链接脚本决定地址),所以其他c文件编译时只会看到这个函数的声明而无法知道她的实体,就会像普通函数一样通过bl 一个函数地址,等链接的时候再填入该地址了,他做不到内联展开。
所以要内联则必须在每个用到它的c文件体现实体,那就只有在头文件了,所以会把这类希望全局使用又希望增加效率的函数实现在头文件中static inline。
static inline 的坏处
因为inline 是C99才有的关键字,C89没有,有部分编译器不支持,或者部分支持,如支持__inline 或 __inline__等,所以我们一般会用一个宏定义inline 如:
#define INLINE    static inline
不支持inline时:
#define INLINE    static
但是这样如果编译器不支持inline 即意味着之前 static inline的函数全部被修改为 static,在头文件中写static会有什么后果呢?
经过测试果然和我们想的一样,每个c文件包含了该头文件后全部都有了该函数副本。这无疑增大了很多代码量。比如在include.h
这样的大头文件,几乎每个c文件我们都会包含他,相当于每一C文件都会加入一个 static void func(void){...}  实体。如果是函数宏则不会有这种问题,函数宏是没有实际代码的,没调用他时代码不存在。这就是头文件中用static inline 函数的坏处。但是可以通过优化解决,经过测试,O0优化下在头文件中定义static 函数包含该头文件的三个c文件的确都有了该函数,但是在Os优化下则只有调用了该函数的C文件才有实体。这是由编译器对static函数的特性决定的。总之他的法则和我们想的一致,就是头文件仅仅是单纯的展开,而每个C独立编译,不会因为知道其他个C文件定义了该函数,这个c文件就把他当外部bl了。
关于c文件中的static函数
static函数除了文件内使用这个功能外,在优化上也有作用,static定义后如果该文件没有函数调用他,那么他意味着没有用,其他文件不可能调用,所以开优化就被优化掉了(已验证),无优化时则还在。这点一定要注意中断函数最好不要写static,中断函数如果没有中断服务函数的,即没有被调用,static可能被优化,当然也不一定,因为没有中间服务函数的独立中断服务函数必须在链接脚本体现,可能需要再链接脚本上加入KEEP参数应该就没问题。
这里排除非gcc编译器,如code worrior编译器则不同,code worrior是定制型的,通过识别main函数,因此他有主函数枝干可以判断哪些函数被调用,哪些是无用的,但是gcc不同,没有所谓的main,所以三个c文件如果没有static的函数,即使开优化也都会编译出来,他并不知道哪些函数有用,哪些函数无用。而static后他就一定知道他没被调用即无用,所以可以优化掉。
以上均指arm-none-eabi-gcc环境下测试的结论,其他编译器有些不同。但是c语言的编译规则还是以gcc为标准,即使其他编译器有些不同我们平时编程时还是以这个为标准。
在codeworrior 编译器上测试,即使0优化依然会把inline内联,有main函数,没有被主干调用的都是无用函数全部被标记UNUSED,不编译,因此上面讨论的当不支持inline时static函数实体过多的问题它也不存在。

关于头文件中的 static inline函数相关推荐

  1. C语言中:在头文件中使用static定义变量意味着什么?

    C语言中:在头文件中使用static定义变量意味着什么? 看到有一位同学在头文件中这么写: static const wchar_t* g_str1 = - static const wchar_t* ...

  2. 将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中

    将类的定义放在头文件中,把成员函数的实现代码放在一个cpp文件中 写这种.h和.cpp文件分开的大程序,虽然对很多人来说很简单,对自己来说算是第一次吧,好好学C++,加油~ 题目:定义Point类,由 ...

  3. c语言头文件中定义inline static相关函数的优劣

    头文件中常见static inline函数,于是思考有可能遇到的问题,如头文件经常会被包含会不会产生很多副本?网上说法不一.于是自己验证.经过arm-none-eabi-gcc下测试后得出结论. in ...

  4. 头文件中能否进行函数的定义

    通常我们使用头文件时都是在头文件中进行声明,在源文件中定义,哪我们能否在头文件中进行函数的定义 我们先进行一个测试,先声明一个test.h和一个test.cpp文件,并且在test.h中定义一个函数和 ...

  5. C++中头文件中定义的变量

    1.在头文件.h中定义static变量,如: static int x;其实就等效于每个引用该头文件的源文件中,定义一个变量名为x的整型静态全局变量,每个文件中的x变量均属于本源文件,各文件中的互不相 ...

  6. 将函数实现放在头文件中

    研究一个开源算法库,采用C++模板编程,所有函数实现都放在了头文件中,现在把模板去掉,链接时发生冲突,具体原因如下: 因为多个源文件包含了含有函数定义的头文件,在编译的时候,每个源文件都会包含一份函数 ...

  7. C语言如何引用别的文件中的static函数

    文章目录 C如何引用别的文件中的static函数 如果是static函数呢? 缺点是我必须在haha中使用my_static,有时候你可能不想立即使用my_static 试验一下 这样就可以在主函数中 ...

  8. [原创]Enterprise Architecture V7.5 C++代码生成时,头文件中函数声明没有注释,CPP中函数定义却有注释。...

    这几天一直在用Enterprise Architecture来抽象项目中要用到的一些数据结构和类,然后都做得差不多了之后发现,生成代码的时候.h文件中类成员函数部分没有注释,但是.cpp文件中的函数定 ...

  9. C++STL中string的头文件中的常用函数

    文章目录 STL简介 头文件 初始化操作 实现效果 基本函数 1.size,length,capacity 2.resize,reserve 1,2的实现代码 实现效果 3.at,append,ins ...

最新文章

  1. 全差分运算放大器ADA4940的分析
  2. 网络推广外包“重拳出击”中小企业网站优化力求超越网络推广外包行业站
  3. C#-datagriview的表头高度的设置
  4. 46 FI配置-财务会计-固定资产-一般评估-指定平行货币的使用
  5. 补习系列(6)- springboot 整合 shiro 一指禅
  6. Eclipse调试提示:Breakpoint attribute problem: installation failed
  7. redis 实验(八)可视化监控RedisLive
  8. 有道词典 Chrome取词插件
  9. ViBe算法核心思想
  10. bios error 装系统acpi_WIN10重装系统提示错误ACPI?处理重装系统bios acpi错误
  11. 简单枚举 / 枚举排列
  12. 红米8A的root步骤(MIUI 11.0.10.0 稳定版 安卓9)
  13. Audacity如何改变音频节奏?Audacity调整音频节奏方法
  14. 12月15-16日:跟着猫叔写代码学习api接口开发小程序
  15. nodejs+vue+mysql的高校二手跳蚤市场交易网站express
  16. Ubuntu根目录结构说明
  17. 东华理工大学计算机考研资料汇总
  18. Android自己定义TabActivity(实现仿新浪微博底部菜单更新UI)
  19. python 报错 EOL while scanning string literal
  20. 异步社区本周(4.9-4.15)半价电子书

热门文章

  1. 相似图像搜索的哈希算法思想及实现(差值哈希算法和均值哈希算法)
  2. leetcode133. 克隆图(bfs)
  3. java异步io_Java中的异步IO与异步请求处理
  4. 第一章第一个c#程序上机_我从第一个#100DaysOfCode中学到的东西
  5. google i/o_Google I / O 2017最有希望的突破
  6. Python学习(五)列表的简单操作
  7. Linux 进程间通讯详解一
  8. apiCloud中Frame框的操作,显示与隐藏Frame
  9. 未能加载文件或程序集“Autofac, Version=3.4.0.0,
  10. 2013.11.18—2013.11.22周总结