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 >= ? 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#

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

  1. C语言中qsort函数用法

    C语言中qsort函数用法-示例分析    本文实例汇总介绍了C语言中qsort函数用法,包括针对各种数据类型参数的排序,非常具有实用价值非常具有实用价值. 分享给大家供大家参考.C语言中的qsort ...

  2. C语言中sizeof()的用法

    语法 sizeof有三种语法形式: 1.sizeof(object); //sizeof(对象); 2.sizeof(type_name); //sizeof(类型); 3.sizeof object ...

  3. C/C++语言中const的用法

    1. const 在C和C++中的区别     C++中的const正常情况下是看成编译期的常量,编译器并不为const分配空间,只是在编译的时候将期值保存在名字表中,并在适当的时候折合在代码中. 所 ...

  4. 在不同语言中static的用法

    static (计算机高级语言) 编辑 像在VB,C#,C,C++,Java,PHP中我们可以看到static作为关键字和函数出现,在其他的高级计算机语言如FORTRAN.ALGOL.COBOL.BA ...

  5. C语言中 malloc函数用法

    一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...

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

    原文地址:http://www.jb51.net/article/39685.htm 以下是对C语言中assert的使用方法进行了介绍,需要的朋友可以参考下. assert宏的原型定义在<ass ...

  7. C语言中extern的用法--转

    http://blog.sina.com.cn/s/blog_52deb9d50100ml6y.html 在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的, ...

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

    转自:http://www.dingge.com/main/article.asp?id=10 今天整理了一些#define的用法,与大家共享! 1.简单的define定义 #define MAXTI ...

  9. C语言中#define的用法

    今天整理了一些#define的用法,与大家共享! 1.简单的define定义 #define MAXTIME 1000 一个简单的MAXTIME就定义好了,它代表1000,如果在程序里面写 if(i& ...

随机推荐

  1. php变量那些事:php引擎对变量声明、存储简要分析(ZVAL)

    php中变量有三个基本的特性: 1.变量符号.也就是变量的名称.形象比喻,kv中的key.这个有php引擎的符号表(hash表)管理. 2.变量类型.一个php变量可以是boolean.integer ...

  2. Android中内容观察者的使用---- ContentObserver类详解

    详解:http://blog.csdn.net/qinjuning/article/details/7047607

  3. 【转】DCC32的参数详解

    完整的内容如下: // DCC32编译器的设置说明. // Dcc32 [options] filename [options] // DCC32 [操作选项] 文件名称 [操作选项] // -A&l ...

  4. C# 截取带路径的文件名字,扩展名,等等 的几种方法

    C#对磁盘IO操作的时候,经常会用到这些,路径,文件,文件名字,文件扩展名. 之前,经常用切割字符串来实现, 可是经常会弄错. 尤其是启始位置,多少个字节,经常弄晕. 下面这种方法貌似比较简便: st ...

  5. POJ-1579

    #include <stdio.h> #include <stdlib.h> ][][]; int w(int a,int b,int c){ ||b<=||c<= ...

  6. MongoDB 学习笔记(二)—— MongoDB Shell

    MongoDB自带一个JavaScript shell 可以从命令行中与MongoDB交互,功能非常强大.如在上一节最后一张图所看到,可以执行JavaScript程序. 运行Shell 前提是启动Mo ...

  7. C 实现一个简易的Http服务器

    引言 做一个老实人挺好的,至少还觉得自己挺老实的. 再分享一首 自己喜欢的诗人的一首 情景诗. 每个人总会有问题,至少喜欢就好, 本文 参照 http 协议   http://www.cnblogs. ...

  8. 2天驾驭DIV+CSS (实战篇)(转)

     这是去年看到的一片文章,感觉在我的学习中,有不少的影响.于是把它分享给想很快了解css的兄弟们.本文是实战篇. 基础篇[知识一] “DIV+CSS” 的叫法是不准确的[知识二] “DIV+CSS” ...

  9. git的初步使用

    1.在GitHub上建立项目登录GitHub后,你可以在右边靠中那里找到一个按钮“New Repository”,点击过后,填入项目名称.说明和网址过后就可以创建了,然后会出现一个提示页面,记下类似g ...

  10. 发布项目MVC4-EF6.0出错

    出错: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFram ...