当前位置:   article > 正文

C语言 的内联函数_c语言内联函数

c语言内联函数

通常,函数调用都有一定的开销,因为函数的调用过程包括建立调用、 传递参数、跳转到函数代码并返回。使用宏使代码内联,可以避免这样的开 销。C99还提供另一种方法:内联函数(inline function)。
可能顾名思义地认为内联函数会用内联代码替换函数调用。
其实C99和C11标准中叙述 的是:“把函数变成内联函数建议尽可能快地调用该函数,其具体效果由实 现定义”。因此,把函数变成内联函数,编译器可能会用内联代码替换函数 调用,并(或)执行一些其他的优化,但是也可能不起作用。

创建内联函数的定义有多种方法。标准规定具有内部链接的函数可以成为内联函数,还规定了内联函数的定义与调用该函数的代码必须在同一个文件中。

因此,最简单的方法是使用函数说明符 inline 和存储类别说明符 static。通常,内联函数应定义在首次使用它的文件中,所以内联函数也相当于函数原型。如下所示:

#include <stdio.h>
inline static void eatline()  // 内联函数定义/原型
{
while (getchar() != '\n')
continue;
}
int main()
{
...
eatline();       // 函数调用
...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

编译器查看内联函数的定义(也是原型),可能会用函数体中的代码替换 eatline()函数调用。也就是说,效果相当于在函数调用的位置输入函数体 中的代码:

#include <stdio.h>
inline static void eatline() //内联函数定义/原型
{
while (getchar() != '\n')
continue;
}
int main()
{
...
while (getchar() != '\n') //替换函数调用
continue;
...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

由于并未给内联函数预留单独的代码块,所以无法获得内联函数的地址
(实际上可以获得地址,不过这样做之后,编译器会生成一个非内联函数)。另外,内联函数无法在调试器中显示。
内联函数应该比较短小。把较长的函数变成内联并未节约多少时间,因 为执行函数体的时间比调用函数的时间长得多。

编译器优化内联函数必须知道该函数定义的内容。这意味着内联函数定义与函数调用必须在同一个文件中。鉴于此,一般情况下内联函数都具有内部链接。因此,如果程序有多个文件都要使用某个内联函数,那么这些文件中都必须包含该内联函数的定义。最简单的做法是,把内联函数定义放入头文件,并在使用该内联函数的文件中包含该头文件即可。

// eatline.h
#ifndef EATLINE_H_
#define EATLINE_H_
inline static void eatline()
{
while (getchar() != '\n')
continue;
}
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

一般都不在头文件中放置可执行代码,内联函数是个特例。因为内联函数具有内部链接,所以在多个文件中定义同一个内联函数不会产生什么问题。
与C++不同的是,C还允许混合使用内联函数定义和外部函数定义(具有外部链接的函数定义)。例如,一个程序中使用下面3个文件:

//file1.c
...
inline static double square(double);
double square(double x) { return x * x; }
int main()
{
double q = square(1.3);
...
//file2.c
...
double square(double x) { return (int) (x*x); }
void spam(double v)
{
double kv = square(v);
...
//file3.c
...
inline double square(double x) { return (int) (x * x + 0.5); }
void masp(double w)
{
double kw = square(w);
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

如上述代码所示,3个文件中都定义了square()函数。file1.c文件中是 inline static定义;file2.c 文件中是普通的函数定义(因此具有外部链接); file3.c 文件中是 inline 定义,省略了static。
3个文件中的函数都调用了square()函数,这会发生什么情况?。file1.c 文件中的main()使用square()的局部static定义。由于该定义也是inline定义, 所以编译器有可能优化代码,也许会内联该函数。file2.c 文件中,spam()函 数使用该文件中 square()函数的定义,该定义具有外部链接,其他文件也可 见。file3.c文件中,编译器既可以使用该文件中square()函数的内联定义,也 可以使用file2.c文件中的外部链接定义。如果像file3.c那样,省略file1.c文件 inline定义中的static,那么该inline定义被视为可替换的外部定义。
注意GCC在C99之前就使用一些不同的规则实现了内联函数,所以GCC 可以根据当前编译器的标记来解释inline。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/626826
推荐阅读
相关标签
  

闽ICP备14008679号