C 语言内联函数为什么在.h中声明称 static inline *(); 为什么通常要加上static呢?

C 语言内联函数为什么在.h中声明称 static inline *(); 为什么通常要加上static呢?,第1张

可以不声明成静态的,另一方面虽然内联函数可以加快调用的速度,但是调用次数多的话,会使可执行文件变大,这样会降低速度。static 修饰的内联函数,一般情况下不会产生函数本身的代码,而是全部被嵌入在被调用的地方。如果不加static,则表示该函数有可能会被其他编译单元所调用,所以一定会产生函数本身的代码。

inline int foo(int a, int b) { return a + b} int main(int argc, char *argv[]){return(1,2)

*ANSI C, ISO/IEC C89/C90:标准中没有inline关键字.

*GNU C89/C90:

1、static inline:函数名标识符的作用域为当前编译单元(translation unit),允许其他编译单元中有重名定义. 这里的inline建议编译器,函数在被调用时可以直接展开函数体,但是否展开取决于编译器.(譬如,如果优化级别为-O0,则必须按函数地址调用,此时编译器会忽略inline请求,将函数编译为普通函数;或者,出现了递归调用,编译器也无法内联这个函数)

2、inline:在当前编译单元内,和static inline语义相同,都是建议编译器在当前编译单元内展开函数体(是否展开取决于编译器). 但同时编译器会对该函数生成一份普通函数的代码,在其他编译单元内可以调用,与普通的extern函数调用无异.

3、extern inline:相当诡异. 这样的函数定义只为内联而提供. 如果强行用普通函数调用方式调用该函数(譬如,优化级别为-O0,或者按函数指针调用),则链接器会认为存在另一个同名的普通函数. 如果没有这个同名普通函数的定义,则链接器会报告找不到符号.

*ISO/IEC C99/C11:

1、static inline:和GNU C89/C90中的语义完全相同.

2、inline:很类似GNU C89/C90中的extern inline. 标准文档中的解释相当晦涩:允许(但不要求)编译器在当前编译单元内展开函数体(原文的描述是“相比正常的函数调用机制,让内联函数调用尽可能快”,而文档下面的脚注中提到,可能的选择是“内联替换”,见ISO/IEC 9899:1999或ISO/IEC 9899:2011),是否内联由编译器设计者自行决定,同时也允许外部存在同名的普通函数定义. 经测试最新版本的Clang和GCC在标准-std=c99和-std=c11下会在可以内联的情况下(例如优化级别为-O2)采用内联版本.

3、但标准文档中同时也规定了,若在函数声明中加入extern,则相应的内联函数定义成为所谓的外部定义,行为和GNU C89/C90的inline相同:在当前编译单元中建议编译器展开函数体,同时生成一份普通函数的代码,在其他编译单元中也可调用.

4、extern inline:标准文档中未见extern inline的定义.

*GNU C99/C11:采用与ISO/IEC C99/C11相同的语义.

最新版本的Clang和GCC默认均采用GNU C11标准,因此会出现不优化代码时找不到内联函数符号的错误.


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8142976.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-13
下一篇 2023-04-13

发表评论

登录后才能评论

评论列表(0条)

保存