首页 > 其他分享 >内联函数inline

内联函数inline

时间:2023-02-16 14:13:21浏览次数:30  
标签:定义 double average 内联 inline 函数

在机器层面,调用函数之前可能需要预先执行一些指令。调用本身需要跳转到函数的第一条指令,函数本身可能也需要执行一些格外的指令来启动执行。如果函数有参数,参数需要被复制(因为C通过值传递参数)。从函数返回也需要被调用的函数和调用函数执行差不多工作量。调用函数和从函数返回所需的工作量称为“额外开销”,因为我们并没有要求函数执行这些工作。尽管函数调用中的额外开销只是使程序稍许变慢,但在特定的情况下额外开销会产生累积效应。例如,在函数需要调用数百万次或数十亿次,使用老式的比较慢的处理器(例如在嵌套系统中),或者有着非常严格的时限要求(例如在实时系统中)时。

C89中,避免函数额外开销的唯一方式是使用带参数的宏,但是带参数的宏也有一些缺点。C99提供了一种更好的解决方案:创建内联函数(inline function)。“内联”表明编译器把函数的每一次调用都用函数的机器指令来代替。这种方法虽然会使被编译程序的大小增加一些,但是可以避免函数调用的常见额外开销。

不过,把函数声明为inline并不是强制编译器将代码内联编译,只是建议编译器应该使函数调用尽可能地快,也许在函数调用时才执行内联展开。编译器可以忽略这一建议。从这方面来说,inline类似于registerrestrict关键字,后两者也是用于提升程序性能的,但可以忽略。

内联定义

内联函数用关键字inline作为一个声明说明符:

inline double average(double a, double b)
{
    return (a + b) / 2;
}

下面考虑复杂一点的情形。average有外部链接,所以在其他源文件也可以调用average。但是编译器并没有考虑average的定义是外部定义(它是内联定义),所以试图在别的文件中调用average将被认为是错误的。

有两种方法可以避免这一错误。一种方法是在函数定义中增加单词static

static inline double average(double a, double b)
{
    return (a + b) / 2;
}

现在average具有内部链接了,所以其他文件不能调用它。其他文件可以定义自己的average函数,可以与这里的定义相同,也可以不同。

另一种方法是为average提供外部定义,从而可以在其他文件中调用。一种实现方式是将该函数重新写一遍(不使用inline),并将这一函数定义放在另一源文件中。这样做是合法的,但为同一个函数提供两个版本不太可取,因为我们不能保证对程序进行修改时它们仍然一致。

更好一些的实现方式是,首先将average的内联定义放入头文件(命名为average.h)中:

#ifndef AVERAGE_H
#DEFFINE AVERAGE_H

inline double average(double a, double b)
{
    return (a + b) / 2;
}

#endif

接下来,再创建与之匹配的源文件average.c

#include "average.h"

extern double average(double a, double b);

现在,任何一个需要调用average函数的文件只需要简单地包含average.h就行了,该头文件包含了average的内联定义。average.c文件包含了average的原型。由于使用了extern关键字,因此average.h中的average的定义在average.c中被认为是外部定义。

C99中的一般法则是,如果特定文件中某个函数的所有顶层声明中都有inline但没有extern,则该函数定义在该文件中是内联的。如果在程序的其他地方使用该函数(包含其内联定义的文件也算),则需要在另一个文件中为其提供外部定义。调用函数时,编译器可以选择进行正常调用(使用函数的外部定义)或者执行内联展开(使用函数的内联定义)。我们没有办法知道编译器会怎样选择,所以一定要确保这两外定义一致。刚刚我们讨论的方式(使用average.haverage.c)可以保证定义的一致性。

标签:定义,double,average,内联,inline,函数
From: https://www.cnblogs.com/matrioc/p/17126452.html

相关文章