当前位置:  编程技术>c/c++/嵌入式

C语言中的内联函数(inline)与宏定义(#define)详细解析

    来源: 互联网  发布时间:2014-10-20

    本文导语:  先简明扼要,说下关键:1、内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指令,这样在运行时速度更快。2、内联函数可以调试,而宏定义是不可以调试的。内联函数...

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

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

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

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

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

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

 
三、为什么我应该用内联函数?而不是原来清晰的 #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 关键字,并且将定义放入头文件:inlinevoid f(int i, char c){   // ...}
注意:将函数的定义({...}之间的部分)放在头文件中是强制的,除非该函数仅仅被单个 .cpp 文件使用。尤其是,如果你将内联函数的定义放在 .cpp 文件中并且在其他 .cpp文件中调用它,连接器将给出 “unresolved external” 错误。

五、如何告诉编译器使一个成员函数成为内联函数?
声明内联成员函数看上去和普通函数非常类似:
class Fred {public:  
void f(int i, char c);};
但是当你定义内联成员函数时,在成员函数定义前加上 inline 关键字,并且将定义放入头文件中:inlinevoid 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),并使用好它们,对我们是大有裨益的。(注:本文部分内容来源于网络整理,上述探讨属于个人意见,仅供参考。错误之处也是难免!)

    
 
 

您可能感兴趣的文章:

  • 关于C语言内联函数
  • Linux下C语言strstr()查找子字符串位置函数详细介绍(strstr原型、实现及用法)
  • java 的条件判断函数(类似于别的语言iif函数)
  • Unix系统函数和C语言标准函数库有重叠的部分吗?
  • c语言也能重载函数? 怎么解释。unix编程的open函数。
  • SAC函数式编程语言
  • 我在c语言下建立一个函数,难道不能在函数名称前加 void 么?
  • 在Unix下C语言中的SignalInit函数怎么用
  • Linux添加系统调用时如何调用C语言库函数
  • C语言中函数声明与调用问题
  • c语言 字符串函数 子串
  • C语言哈希函数库 murmur3
  • C语言字符串函数库 Strfunc
  • 常用C语言函数库 libasn
  • 如何实现类似PHP.PB等语言中eval的函数功能?
  • 哪里有linux下C语言库函数手册?
  • 何处可得 标准C语言函数源代码?
  • LINUX C语言中,用什么函数可以设置日期和时间?
  • 函数式编程语言 Whiley
  • linux下C语言怎么没有getch()函数?
  • 怎么阅读c语言的程序?到什么地方找每个函数都是做什么的?
  • C语言中什么函数可以设置程序的当前工作路径
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • C语言二维条形码解析库 libqrencode
  • C语言的XML解析器 iksemel
  • 用C语言如何组装和解析XML报文???
  • C 语言的 JSON 解析器 BeneJSON
  • 表达式语言解析器 Commons EL
  • C语言的异步DNS解析库 c-ares
  • C语言DNS解析器 dns.c
  • C语言的HTML解析库 libhtml
  • 请问脚本语言 解析器的工作原理?
  • 在做FTP服务端,请问哪位有解析LIST命令的C语言代码?
  • 纯C语言实现的HTML5解析库 Gumbo
  • C语言解析XML报文的问题
  • 深入解析C语言中常数的数据类型
  • 解析c语言中"函数调用中缺少哨兵"的情况分析
  • C语言static修饰函数详细解析
  • C语言的指针类型详细解析
  • c语言中static和extern的用法详细解析
  • 解析c语言switch中break语句的具体作用
  • 解析C语言中位字段内存分配的问题
  • C语言typedef与复杂函数声明问题的深入解析
  • 2013年7月和2013年8月编程语言排行榜
  • 如何在GTK2.0下实现国际化(语言选择根据自己设置的语言,不用系统的语言)
  • 2017 年热门编程语言排行榜出炉,你的语言上榜没?
  • C语言中有指针,因此C语言可以创建链表,那么Java语言没有指针,那Java是否可以创建链表呢?
  • 苹果OS X和IOS下最新编程语言swift介绍
  • 求助,在linux下,c语言和汇编语言的接口是什么?
  • linux下C语言怎么没有getch()函数? iis7站长之家
  • C语言中间语言 CIL
  • PHP编程语言介绍及安装测试方法
  • 最近学JSP,苦于HTML语言和JAVA语言太差,请教推荐几本书,thanks.
  • c语言实现MD5算法完整代码示例


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3