江门营销型网站建设,wordpress qq快捷登陆,微信管理系统在哪里找,企业网站建设服务优势文章目录 前言1. 内联函数被创造出来的意义2. 内联函数的概念2.1 内联函数在代码中的体现2.2 普通函数和内联函数的汇编代码 3. 内联函数的特性#xff08;重点#xff09;4. 总结 前言
本章来聊一聊C的创作者本贾尼大佬#xff0c;为什么要创作出… 文章目录 前言1. 内联函数被创造出来的意义2. 内联函数的概念2.1 内联函数在代码中的体现2.2 普通函数和内联函数的汇编代码 3. 内联函数的特性重点4. 总结 前言
本章来聊一聊C的创作者本贾尼大佬为什么要创作出内联函数以及内联函数的定义和内联函数的实现机制等等。
话不多说让我们直入主题
1. 内联函数被创造出来的意义
请大家先看下面的代码
#includestdio.h
int Add(int x, int y)
{return xy;
}int main()
{int ret Add(10, 20);//假设下面有很多地方都要用到Add函数return 0;
}假设Add函数在主函数中有非常多的地方要使用到我们的这种写法是最好的吗 其实我们这种写法并不好。从函数调用的效率来看每当我们调用一次函数就要在栈区上开辟一块空间用作函数栈帧等函数调用完之后栈帧就会被销毁。但是在栈区上开辟空间以及栈帧的销毁都是会浪费时间资源的更何况同一个函数调用很多次的情况。 那我们该怎么做呢有一个办法就是将这个函数以一种绕开编译器在调用函数时会开辟函数栈帧的做法——“宏函数”。
#includestdio.h
//宏函数的写法
#define Add(x,y) ((x)(y))int main()
{int ret Add(10, 20);//假设下面有很多地方都要用到Add函数return 0;
}宏函数的工作原理就是在编译处于预处理阶段时就会在使用宏函数的地方将对应的代码给替换进去。这样就相当于只是一个代码段了而不是一个函数。
但是宏函数的写法实在是太容易出错了而且使用宏函数还有以下的缺点
代码的可读性差不方便调试复杂
了解了上述场景之后我们就来了解一下C的祖师爷是如何攻克这个难关的。
C的祖师爷也发现了这个问题于是他就创造出了一个函数内联函数这个函数能够完美的实现上述宏函数的功能和解决和宏函数的缺点。
2. 内联函数的概念
从形式上看以关键字inline开头的函数叫做内联函数。 从功能上看C编译器在调用内联函数的地方展开函数体对应的内容没有函数调用的消耗提高效率。
内联函数的写法
//在函数定义的开头加一个inline关键字
inline int Add(int x, int y)
{return x y;
}如果在上述的函数增加了inline关键字在编译期间编译器会用函数体替换函数的调用。
那我们该怎么查看这个现象呢可以通过查看汇编代码来判断
2.1 内联函数在代码中的体现
VS查看方式
在release模式下查看编译器生成的汇编代码中是否存在call Add。这种方法本人不推荐因为在release模式下代码不容易调试在debug模式下需要对编译器进行设置否则不会展开(因为debug模式下编译器默认不会对代码进行优化)
按我们就得更改一下Debug下的配置信息 第一步点击项目文件夹选择C/C,之后点击常规在调试信息格式中选择程序数据库模式。
第二步继续在C/C选项卡下选择优化在内联函数拓展这块选择只适用于__inline(/0b1)
2.2 普通函数和内联函数的汇编代码
(这里只是举个例子) 普通函数的汇编代码 内联函数的汇编代码 对比一下内联函数和普通函数的汇编代码的区别。可以看到的是对于普通函数的调用编译器是根据call指令来执行的。而对于内联函数来说C编译器则是直接将函数体里面的内容转换成汇编代码替换到了函数调用的地方。 3. 内联函数的特性重点
1. inline是一种以空间换时间的做法如果编译器将函数当成内联函数处理在编译阶段会用函数体替换函数调用缺陷可能会使目标文件变大优势 少了调用开销提高程序运行效率。 2. inline对于编译器而言只是一个建议不同编译器关于inline实现机制可能不同一般建议将函数规模较小(即函数不是很长具体没有准确的说法取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰否则编译器会忽略inline特性。 3. inline不建议声明和定义分离分离会导致链接错误。因为inline被展开就没有函数地址了链接就会找不到。
// F.h
#include iostream
using namespace std;
inline void f(int i);// F.cpp
#include F.h
void f(int i)
{cout i endl;
}
// main.cpp
#include F.h
int main()
{f(10);return 0;
}
// 链接错误main.obj : error LNK2019: 无法解析的外部符号 void __cdecl
//f(int) (?fYAXHZ)该符号在函数 _main 中被引用4. 总结
本文讲解了内联函数内联函数是否能够成功实现具体取决于编译器的做法我们只是给编译器提一个意见。还有一个重要的点是我们定义和声明内联函数时得两边都用inline否则因为inline的作用会使得函数的地址变成代替函数体的代码段的地址在链接阶段会因为找不到这个函数而报错 好了本文就讲到这里了。如果觉得本文好不错的话麻烦给偶点个赞吧