首页 > 编程知识 正文

c语言内联函数,为什么内联函数

时间:2023-05-05 10:59:25 阅读:223324 作者:2066

【注:本文只讨论C语言中的内联函数,暂不谈论C++,因为C++中这块知识相对要更复杂。】

什么是内联函数

在C语言中,如果一些函数被频繁调用,不断地有函数入栈,即函数栈,会造成栈空间或栈内存的大量消耗。
为了解决这个问题,特别的引入了inline修饰符,表示为内联函数。
内联函数是代码被插入到调用者代码处的函数。内联函数通过避免被调用的开销来提高执行效率

采用内联函数实质是以空间换时间的做法

举例:

void myprintf(int a){printf(“%d”,a);}int main(){for(i=0;i<100;i++)myprintf(i);}

对于这个函数,在进行反复的打印i的过程中我们是不是要反复的调用myprintf()这个函数,进函数和出函数是需要时间的(入栈出栈),假设这个过程用时为4ms,而执行printf这个操作只需要2ms,那么在100次循环的过程中进出函数的时间比函数功能printf需要的时间还要长,这样很影响工作效率。于是,我们就想要如何避免进出函数的过程呢?可以声明inline这个关键字。

inline void myprintf(int a){printf(“%d”,a);}int main(){for(i=0;i<100;i++)myprintf(i);}

main函数中的myprintf(i);会直接替换成该函数主体,上面的代码在编译时实际上是这样的:

inline void myprintf(int a){printf(“%d”,a);}int main(){for(i=0;i<100;i++){printf(“%d”,i);}} 内联函数和宏定义区别

内联函数看上去和宏定义非常相似。
对于上面的例子,我们可以用宏定义实现:

#define MYPRINTF(a) printf(“%d”,a);int main(){for(i=0;i<100;i++)MYPRINTF(i);}

效果可以说与前面使用内联的方式没多大差别。
但宏定义在某些情况下会有问题,比如:

// 返回 i 的绝对值的宏#define abs1(i) ( (i) >= 0 ? (i) : -(i) )// 返回 i 的绝对值的内联函数inline int abs2(int i){ return i >= 0 ? i : -i;}int fun();void userCode(int x){ int ans; ans = abs1(x++); // 错误!x 被增加两次 ans = abs1(fun()); // 错误!fun()被调用两次 ans = abs2(x++); // 正确! x 被增加一次 ans = abs2(fun()); // 正确! fun() 被调用一次}

ans = abs1(x++); 展开是ans = ( (x++) >= 0 ? (x++) : -(x++) );
所以x++会执行2次,这可能是用户所不希望的。

内联函数,与直接的函数调用区别仅在于没有函数调用过程的消耗。保留了函数调用的特性,又提高函数的执行效率。

和宏不同的,还有内联函数的参数类型被检查,并且被正确地进行必要的类型转换。

使用内联函数注意事项

1、inline只适合函数体内代码量少的函数使用,因为每一处内联函数的调用都要复制代码,如果该函数代码量较大,将使程序的总代码量增大,消耗更多的内存空间。

2、内联函数本身不能是直接递归函数(自己内部还调用自己的函数)。因为这样会在编译时无穷无尽地展开。

3、如果执行函数体内代码的时间,相比于函数调用的时间开销较大,那么使用内联的效率的收获会很少。比如函数内有循环,这种情况就不考虑用内联函数了。

4、关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。

inline void Foo(int x, int y); // inline 仅与函数声明放在一起void Foo(int x, int y){}

5、对于功能复杂,内容较多的函数,即使加上inline修饰符,也不一定能作为内联函数,因为编译器会判定做优化。

关于static inline

static inline的内联函数,一般情况下不会产生函数本身的代码,而是全部被嵌入在被调用的地方。如果不加static,则表示该函数有可能会被其他编译单元所调用,所以一定会产生函数本身的代码。所以加了static,一般可令可执行文件变小。—【存疑,不确定】

static inline的内联函数,只能在本文件内调用,而没有static则可以被其他文件调用,这与static的常用方法一致。

函数的地址被使用的时候。如通过函数指针对函数进行了间接调用。这种情况下就不得不为static inline函数生成独立的汇编码,否则它没有自己的地址。

参考鸣谢:

https://blog.csdn.net/zqixiao_09/article/details/50877383

https://www.cnblogs.com/linux-bfbdxj520/p/11405474.html

https://www.jb51.net/article/41520.htm

https://blog.csdn.net/chuqierliang/article/details/48053417

https://blog.csdn.net/weixin_33895657/article/details/92037511

https://blog.csdn.net/qq_33757398/article/details/81390151

https://blog.csdn.net/weixin_30706507/article/details/96192546

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。