在头文件中 ,inline 函数的定义前加static的目的是什么?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_31213895/article/details/83247675

先看一下头文件中定义的一段static 的inline 代码

static inline long get_micros()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return static_cast<long>(tv.tv_sec) * 1000000 + tv.tv_usec;
}

为什么要在头文件中定义static inline函数呢?

一些简单的封装接口函数,如 open() { vfs_open() } 仅仅是为了封装一个接口,我们不希望耗费一次函数调用的时间,解决方法一是宏,但是作为接口,宏不够清晰。那选择inline,但是如果在.cpp文件中写:
main.cpp

inline void open(void)
{
    vfs_open();
} 

头文件加声明,外部要使用则不会内联的,因为编译器有个原则,以cpp文件为单位进行逐个编译obj,每个cpp文件的编译是独立的,该cpp文件用到的外部函数都在编译时预留一个符号,只有等到所有obj生成后链接时才给这些符号地址(链接脚本决定地址),所以其他cpp文件编译时只会看到这个函数的声明而无法知道她的实体,就会像普通函数一样通过bl1 一个函数地址,等链接的时候再填入该地址了,它做不到内联展开。
所以要内联则必须在每个用到它的cpp文件体现实体,那就只有在头文件了,所以会把这类希望全局使用又希望增加效率的函数实现在头文件中static inline。
一般定义内联在.cpp文件中。声明什么的在头文件中,inline可写也可不写,如果有哪里需要这个内联,
引用声明文件的同时,也需要再定义一遍这个内联函数,好麻烦。于是就有在头文件中定义内联函数的方式,在inline前加static。

风险:

static inline 的坏处:
因为inline 是C99才有的关键字,C89没有,有部分编译器不支持,或者部分支持,如支持__inline 或 __inline__等,所以我们一般会用一个宏定义inline 如:

#define INLINE    static inline

不支持inline时:

#define INLINE    static

这样如果编译器不支持inline 即意味着之前 static inline的函数全部被修改为 static,在头文件中写static会有什么后果呢?
每个cpp文件包含了该头文件后全部都有了该函数副本。这无疑增大了很多代码量。比如在include.h 这样的大头文件中,几乎每个cpp文件我们都会包含他,相当于每一cpp文件都会加入一个 static void func(void){…} 实体。如果是函数宏则不会有这种问题,函数宏是没有实际代码的,没调用他时代码不存在。这就是头文件中用static inline 函数的坏处。但是可以通过优化解决,经过测试,O0优化下在头文件中定义 static函数,包含该头文件的三个cpp文件的确都有了该函数,但是在Os优化下则只有调用了该函数的cpp文件才有实体。这是由编译器对static函数的特性决定的。总之他的法则和我们想的一致,就是头文件仅仅是单纯的展开,而每个cpp独立编译,不会因为知道其他的cpp文件定义了该函数,这个cpp文件就把他当外部bl了。
感谢
作者:求知君
原文:https://blog.csdn.net/huanghui167/article/details/41346663


  1. bl的解释
    bl用于子程序跳转,要返回地址,返回地址存于LR中。当发生bl跳转前,会在寄存器 R14 (即LR)中保存当前PC-4,即bl跳转指令的下一条指令的地址。所以在返回时只要 MOV pc,lr 。
    b用于不返回的跳转,比如跳到某个标号处,b . 其中的‘.’代表当前地址,那么 b . 就是死循环。 ↩︎

展开阅读全文

没有更多推荐了,返回首页