函数调用会有一定的开销,因为函数的调用过程包括建立调用、传递参数、跳转到函数代码并返回。
通过宏使代码内联,可以避免函数调用的开销;不过,使用宏容易出问题,C99 提供了另一种方法“内联函数”。将函数变成内联函数,编译器可能会使用内联代码替换函数调用,并执行一些其它的优化。
C 标准规定:具有内部链接的函数可以成为内联函数。内联函数的定义与调用该函数的代码必须在同一文件中。使用函数说明符inline
和存储类别说明符static
来定义内联函数。
inline static long factorial(int n)//内联函数定义/声明
{
long ans;
for (ans = 1; n > 1; n--)
ans *= n;
return ans;
}
int main(int argc, const char * argv[]) {
long result = factorial(10);//内联函数调用
printf("循环计算阶乘: 10! = %ld \n",result);
return 0;
}
编译器查看内联函数的定义,可能会用函数体中的代码替换factorial()
函数调用,效果相当于在函数调用的位置插入函数体重的代码:
int main(int argc, const char * argv[]) {
long result;
int n = 10;
for (result = 1; n > 1; n--)
result *= n;
printf("循环计算阶乘: 10! = %ld \n",result);
return 0;
}
由于并未给内联函数预留单独的函数块,所以无法获取内联函数的地址(实际上可以获取地址,但是这样做后,编译器会生成一个非内联函数)。另外内联函数无法在调试器中显示。
一般而言,内联函数比较短小,把较长的函数变成内联函数并未节约多少时间,因为执行函数体的时间比调用函数的时间长得多。
编译器优化内联函数必须知道该函数定义的内容:这要求内联函数与函数调用必须定义在同一个文件中。一般情况下,内联函数都具有内部链接。
如果多个文件使用要某个内联函数,那么这些文件都必须包含这个内联函数。我们可以将这个内联函数定义在某个头文件,在使用该内联函数的文件包含该头文件即可:
#ifndef LineIN_h
#define LineIN_h
inline static long factorial(int n)//内联函数定义/声明
{
long ans;
for (ans = 1; n > 1; n--)
ans *= n;
return ans;
}
#endif
一般都不在头文件放置可执行代码,但内联函数是个特例。内联函数具有内部链接,所以在多个文件定义同一个内联函数不会有什么问题。
网友评论