C语言中inline的用法

C语言里面的内联函数(inline)与宏定义(#define)探讨

先简明扼要,说下关键

1、内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指令,这样在运行时速度更快。

2、内联函数可以调试,而宏定义是不可以调试的。

内联函数与宏本质上是两个不同的概念如果程序编写者对于既要求快速,又要求可读的情况下,则应该将函数冠以inline。下面详细介绍一下探讨一下内联函数与宏定义。

一、内联函数是什么?

  内联函数是代码被插入到调用者代码处的函数。如同
#define
宏(但并不等同,原因见下文),内联函数通过避免被调用的开销来提高执行效率,尤其是它能够通过调用(“过程化集成”)被编译器优化。

二、
内联函数是如何在安全和速度上取得折衷?

  在 C
中,你可以通过在结构中设置一个 void* 来得到“封装的结构”,在这种情况下,指向实际数据的 void*
指针对于结构的用户来说是未知的。因此结构的用户不知道如何解释void*指针所指内容,但是存取函数可以将 void*
转换成适当的隐含类型。这样给出了封装的一种形式。

  不幸的是这样做丧失了类型安全,并且也将繁琐的对结构中的每个域的访问强加于函数调用。(如果你允许直接存取结构的域,那么对任何能直接存取的人来说,了解如何解释
void* 指针所指内容就是必要的了;这样将使改变底层数据结构变的困难)。

  虽然函数调用开销是很小的,但它会被累积。C++类允许函数调用以内联展开。这样让你在得到封装的安全性时,同时得到直接存取的速度。此外,内联函数的参数类型由编译器检查,这是对
C 的 #define 宏的一个改进。

三、为什么我应该用内联函数?而不是原来清晰的
#define
宏?

  和
#define
宏不同的是,内联函数总是对参数只精确地进行一次求值,从而避免了那声名狼藉的宏错误。换句话说,调用内联函数和调用正规函数是等价的,差别仅仅是更快:

// 返回 i 的绝对值的宏
#define unsafe(i) ( (i) >= 0 ? (i) : -(i) )

// 返回 i 的绝对值的内联函数
inline int safe(int i)
{
return i >= 0 ? i : -i;
}

int f();

void userCode(int x)
{
int ans;
ans = unsafe(x++); // 错误!x 被增加两次
ans = unsafe(f()); // 危险!f()被调用两次
ans = safe(x++); // 正确! x 被增加一次
ans = safe(f()); // 正确! f() 被调用一次
}

  和宏不同的,还有内联函数的参数类型被检查,并且被正确地进行必要的转换。

  宏定义复杂函数是有害的;非万不得已不要用。

四、如何告诉编译器使非成员函数成为内联函数?

  声明内联函数看上去和普通函数非常相似:

void
f(int i, char c);

  当你定义一个内联函数时,在函数定义前加上
inline 关键字,并且将定义放入头文件

inline
void f(int i, char c)

{

//
...

}

  注意:将函数的定义({...}之间的部分)放在头文件中是强制的,除非该函数仅仅被单个
.cpp 文件使用。尤其是,如果你将内联函数的定义放在 .cpp 文件中并且在其他 .cpp文件中调用它,连接器将给出 “unresolved
external” 错误。

五、如何告诉编译器使一个成员函数成为内联函数?

  声明内联成员函数看上去和普通函数非常类似:

class
Fred {

public:

void f(int i, char c);

};

但是当你定义内联成员函数时,在成员函数定义前加上
inline 关键字,并且将定义放入头文件中:

inline

void
Fred::f(int i, char c)

{

//
...

}

  通常将函数的定义({...}之间的部分)放在头文件中是强制的。如果你将内联函数的定义放在
.cpp 文件中并且在其他 .cpp 文件中调用它,连接器将给出“unresolved external”错误。

六、
有其它方法告诉编译器使成员函数成为内联吗?

有:在类体内定义成员函数:

class
Fred {

public:

void f(int i, char c)

{

// ...

}

};

尽管这对于写类的人来说很容易,但由于它将类是“什么”(what)和类“如何”(how)工作混在一起.

小结

总之,在嵌入式C(或C++)编程里面,懂得使用内联函数(inline)与宏定义(#define),并使用好它们,对我们是大有裨益的。

http://huxiongwei.spaces.eepw.com.cn/articles/article/item/85841#

时间: 2024-11-10 07:18:58

C语言中inline的用法的相关文章

C语言中qsort函数用法

C语言中qsort函数用法-示例分析  本文实例汇总介绍了C语言中qsort函数用法,包括针对各种数据类型参数的排序,非常具有实用价值非常具有实用价值. 分享给大家供大家参考.C语言中的qsort函数包含在<stdlib.h>的头文件里,本文中排序都是采用的从小到大排序. 一.对int类型数组排序 int num[100]; int cmp ( const void *a , const void *b ) { return *(int *)a - *(int *)b; } qsort(num

浅析C语言中assert的用法(转)

原文地址:http://www.jb51.net/article/39685.htm 以下是对C语言中assert的使用方法进行了介绍,需要的朋友可以参考下. assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:#include <assert.h>void assert( int expression );assert的作用是先计算表达式expression,如果其值为假(即为0),那么它先向标准错误流stderr打印一条出错

(转)C语言中extern的用法

在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”. 1. extern修饰变量的声明.举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v.这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的.这涉及到c语言的另外一个话题--变量的

c语言中assert的用法

1 /************************************************************************* 2 > File Name: assert.c 3 > Author: Mr.Yang 4 > Purpose:演示函数assert的用法 5 > Created Time: 2017年05月29日 星期一 19时57分54秒 6 **************************************************

C语言中sizeof的用法

今天同学问我sizeof可不可以计算结构体的大小,我竟然忘了C语言还有sizeof这个函数,我是多久没有写程序了啊!!!惭愧,上研究生后写嵌入式方面的程序就特别少了,看来以后还要经常来练练手才行.现在转载一篇看到的sizeof用法的文章,与大家分享(第一篇技术类的文章竟然是转载的,惭愧). #include "stdio.h" #include "string.h" #include "stdlib.h" int main() { short i

C语言中#define的用法(转)

今天整理了一些#define的用法,与大家共享! 1.简单的define定义 #define MAXTIME 1000 一个简单的MAXTIME就定义好了,它代表1000,如果在程序里面写 if(i<MAXTIME){.........} 编译器在处理这个代码之前会对MAXTIME进行处理替换为1000. 这样的定义看起来类似于普通的常量定义CONST,但也有着不同,因为define的定义更像是简单的文本替换,而不是作为一个量来使用,这个问题在下面反映的尤为突出. 2.define的“函数定义”

C语言中system函数用法解释

system函数 是可以调用一些DOS命令,比如system("cls");//清屏,等于在DOS上使用cls命令 ================================================================下面列出常用的DOS命令,都可以用system函数调用:ASSOC 显示或修改文件扩展名关联.AT 计划在计算机上运行的命令和程序.ATTRIB 显示或更改文件属性.BREAK 设置或清除扩展式 CTRL+C 检查.CACLS 显示或修改文件的访

C语言中extern的用法

0x01 extern用在变量或函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”. 0x02 extern修饰变量的声明. 举例:若a.c中需引用b.c中的变量int v,可以在a.c中声明extern int v,然后就可以引用变量v;需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到变量v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的.这里涉及到另外一个话题---变量的作用域.能够被其他

C语言中的union用法

union共用声明和共用一变量定义: "联合"是一种特殊的类,也是一种构造类型的数据结构.在一个"联合"内可以定义多种不同的数据类型, 一个被说明为该"联合"类型的变量中,允许装入该"联合"所定义的任何一种数据,这些数据共享同一段内存, 以达到节省空间的目的(还有一个节省空间的类型:位域). 这是一个非常特殊的地方,也是联合的特征. 另外,同struct一样,联合默认访问权限也是公有的,并且,也具有成员函数. 共用体(参考&q