linux下内联函数实现浅析【转】
转自:https://blog.csdn.net/caoyan_12727/article/details/51824073
首先我们来看看内联函数的相关解释:
1.引入目的:为了解决程序中函数调用的效率问题
2. 优点:节省了函数调用时间,也就是说没有call指令(也就没有相关参数的压栈(push),跳转(jmp),返回(ret), 参数出栈(add $0x10,%esp)等等一系类的操作,可谓是节省了不少功夫),以空间换时间.
3. 缺点:在调用出的代码量会增加很多。在编译器没有将相关函数处理成内联函数时(为什么这么说?在一个函数的前面加上inline关键字后,该函数不一定就是内联实现的,加上关键字只是给编译器一个建议而已,至于这个建议编译器接不接受就看需要而定,后面的测试会证明这一点),通常一条跳转指令就可以搞定,但是当编译器将函数处理成内联时,所有关于这个函数的调用指令会被替换成目标函数里所指定功能的相关指令码(至于怎么实现,由编译器决定,此处不深究)。
4. 限制:a.函数不可有循环;b.不能有switch语句; c.不能含有递归和静态变量
本文测试的例子内联函数的定义:
-
-
-
using namespace std;
-
int add(int a,int b){
-
int sum;
-
sum=a+b;
-
return sum;
-
}
-
int main(){
-
int sum=0,a=1,b=2;
-
sum=add(a,b);
-
printf("the sum is :%d\n",sum);
-
return 0;
-
}
首先来看看没有关键字inline的时候main函数的汇编码:
其中call 80485ab <_z3addii>就是对add函数的调用。
下面我们将add函数声明为inline类型:
-
-
-
using namespace std;
-
inline int add(int a,int b){
-
int sum;
-
sum=a+b;
-
return sum;
-
}
-
int main(){
-
int sum=0,a=1,b=2;
-
sum=add(a,b);
-
printf("the sum is :%d\n",sum);
-
return 0;
-
}
让我们再来看看汇编码:
我们依然看到主函数在80485da出对add函数的调用,说明编译器并没用将add函数内联处理。
接下来我们继续修改代码,添加inline int add(int a, int b) __attribute__((always_inline))声明如下;
-
-
-
using namespace std;
-
inline int add(int a, int b) __attribute__((always_inline));
-
inline int add(int a,int b){
-
int sum;
-
sum=a+b;
-
return sum;
-
}
-
int main(){
-
int sum=0,a=1,b=2;
-
sum=add(a,b);
-
printf("the sum is :%d\n",sum);
-
return 0;
-
}
此时的汇编码如下:
可以明显看到,main函数的代码的长度变大,并且多了一条80485e3 01 d0 add %edx ,%eax的指令,这两个寄存器保存的是a和b的值。 将函数处理为内联之后,整个main的代码长度增加了8个字节,试想如果程序中有100处调用,那么就可能多出800字节。这在一定程度上造成了代码的扩张。