当前位置:网站首页>C语言 内联函数
C语言 内联函数
2022-08-02 03:22:00 【a只如初见】
【注:本文只讨论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
边栏推荐
- ThunderBirde无法登录问题、pycharm调试一直收集数据、RuntimeError: CUDA error: device-side assert triggered等疑难杂症解决
- 知识工程作业2:知识工程相关领域介绍
- kettle 安装与配置
- Error: with open(txt_path,'r') as f: FileNotFoundError: [Errno 2] No such file or directory:
- SSM整合
- MySQL中字符串比较大小(日期字符串比较问题)
- About cross-domain issues
- @ApiModel 和 @ApiModelProperty
- 手把手带你 Unity 入门之从零创建一个时钟(GameObjects 与 Scripts)
- JJWT工具类
猜你喜欢

Phospholipid-Polyethylene Glycol-Aldehyde DSPE-PEG-Aldehyde DSPE-PEG-CHO MW: 5000

Redis安装,基本命令,持久化方式,集群

磷脂-聚乙二醇-叠氮,DSPE-PEG-Azide,DSPE-PEG-N3,MW:5000

ThunderBirde无法登录问题、pycharm调试一直收集数据、RuntimeError: CUDA error: device-side assert triggered等疑难杂症解决
![[Basic Tutorial of Remote Control Development 1] Crazy Shell Open Source Formation Drone-GPIO (Remote Control Indicator Light Control)](/img/da/5f6b1ed89cb3fed3cbe6aea840f473.png)
[Basic Tutorial of Remote Control Development 1] Crazy Shell Open Source Formation Drone-GPIO (Remote Control Indicator Light Control)

Problems when yolov5 calls ip camera

Deveco studio 鸿蒙app访问网络详细过程(js)

kettle 安装与配置

新工程加载YOLOV6的预训练权重问题

Mysql8.0安装教程
随机推荐
Debian 10 NTP Service Configuration
Deveco studio Hongmeng app access network detailed process (js)
ModuleNotFoundError No module named 'xxx' possible solutions
「PHP基础知识」PHP中对象的使用
磷脂-聚乙二醇-叠氮,DSPE-PEG-Azide,DSPE-PEG-N3,MW:5000
MySQL中JOIN的用法
DSPE-PEG-Silane,DSPE-PEG-SIL,磷脂-聚乙二醇-硅烷修饰活性基团
ImportError: libGL.so.1: cannot open shared object file: No such file or directory
mysql卸载详细教程
yolov5调用ip摄像头时出现的问题
排序学习笔记(二)堆排序
3分钟带你了解微信小程序开发
磷脂-聚乙二醇-酰肼,DSPE-PEG-Hydrazide,DSPE-PEG-HZ,MW:5000
redis进行持久化时,有新的写操作将如何解决——写时复制
「PHP基础知识」空值(null)的使用
PowerManagerService灭屏超时流程
Redis笔记基础篇:6分钟看完Redis的八种数据类型
磷脂-聚乙二醇-靶向新生血管靶向肽APRPG,DSPE-PEG-APRPG
cross-domain problem solving
@Accessors 注解详解