`
javatoyou
  • 浏览: 1083306 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

inline define区别

 
阅读更多

介绍内联函数之前,有必要介绍一下预处理宏。内联函数的功能和预处理宏的

功能相似。相信大家都用过预处理宏,我们会经常定义一些宏,如

#define TABLE_COMP(x) ((x)>0?(x):0)

就定义了一个宏。

  为什么要使用宏呢?因为函数的调用必须要将程序执行的顺序转移到函数

所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行

该函数前的地方。这种转移操作要求在转去执行前要保存现场并记忆执行的地

址,转回后要恢复现场,并按原来保存地址继续执行。因此,函数调用要有一

定的时间和空间方面的开销,于是将影响其效率。而宏只是在预处理的地方把

代码展开,不需要额外的空间和时间方面的开销,所以调用一个宏比调用一个

函数更有效率。

  但是宏也有很多的不尽人意的地方。

  1、.宏不能访问对象的私有成员。

  2、.宏的定义很容易产生二意性。

我们举个例子:

#define TABLE_MULTI(x) (x*x)

  我们用一个数字去调用它,TABLE_MULTI(10),这样看上去没有什么错误,

结果返回100,是正确的,但是如果我们用TABLE_MULTI(10+10)去调用的话,

我们期望的结果是400,而宏的调用结果是(10+10*10+10),结果是120,这显

然不是我们要得到的结果。避免这些错误的方法,一是给宏的参数都加上括号。

#define TABLE_MULTI(x) ((x)*(x))

  这样可以确保不会出错,但是,即使使用了这种定义,这个宏依然有可能

出错,例如使用TABLE_MULTI(a++)调用它,他们本意是希望得到(a+1)*(a+1)

结果,而实际上呢?我们可以看看宏的展开结果: (a++)*(a++),如果a的值是

4,我们得到的结果是5*6=30。而我们期望的结果是5*5=25,这又出现了问题。

事实上,在一些C的库函数中也有这些问题。例如: Toupper(*pChar++)就会对

pChar执行两次++操作,因为Toupper实际上也是一个宏。

  我们可以看到宏有一些难以避免的问题,怎么解决呢?

  下面就是用我要介绍的内联函数来解决这些问题,我们可以使用内联函数

来取代宏的定义。而且事实上我们可以用内联函数完全取代预处理宏。

  内联函数和宏的区别在于,宏是由预处理器对宏进行替代,而内联函数是

通过编译器控制来实现的。而且内联函数是真正的函数,只是在需要用到的时

候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开

销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一

些问题。

  我们可以用Inline来定义内联函数,不过,任何在类的说明部分定义的函

数都会被自动的认为是内联函数。

  下面我们来介绍一下内联函数的用法。

  内联函数必须是和函数体申明在一起,才有效。像这样的申明

Inline Tablefunction(int I)是没有效果的,编译器只是把函数作为普通的函

数申明,我们必须定义函数体。

Inline tablefunction(int I) {return I*I};

  这样我们才算定义了一个内联函数。我们可以把它作为一般的函数一样调

用。但是执行速度确比一般函数的执行速度要快。

  我们也可以将定义在类的外部的函数定义为内联函数,比如:

Class TableClass{

 Private:

  Int I,j;

 Public:

  Int add() { return I+j;};

  Inline int dec() { return I-j;}

  Int GetNum();

}

inline int tableclass::GetNum(){

return I;

}

  上面申明的三个函数都是内联函数。在C++中,在类的内部定义了函数体的

函数,被默认为是内联函数。而不管你是否有inline关键字。

  内联函数在C++类中,应用最广的,应该是用来定义存取函数。我们定义的

类中一般会把数据成员定义成私有的或者保护的,这样,外界就不能直接读写我

们类成员的数据了。

对于私有或者保护成员的读写就必须使用成员接口函数来进行。如果我们把

这些读写成员函数定义成内联函数的话,将会获得比较好的效率。

Class sample{

 Private:

  Int nTest;

 Public:

  Int readtest(){ return nTest;}

 Void settest(int I) {nTest=I;}

}

  当然,内联函数也有一定的局限性。就是函数中的执行代码不能太多了,如

果,内联函数的函数体过大,一般的编译器会放弃内联方式,而采用普通的方式

调用函数。这样,内联函数就和普通函数执行效率一样了。

宏的使用

/*这一系列文章《C++ Tips》是公司Code Committee专家会推荐工程师看的,感觉很好,拿出来与大家共同提高。并不是知道多少会使人与人产生差别,真正的差别在于你能做到多少。

很多程序员不知道C中的“宏”到底是什么意思?特别是当宏有参数的时候,经常把宏和函数混淆。我想在这里我还是先讲讲“宏”,宏只是一种定义,他定义了一个语句块,当程序编译时,编译器首先要执行一个“替换”源程序的动作,把宏引用的地方替换成宏定义的语句块,就像文本文件替换一样。这个动作术语叫“宏的展开”。使用宏是比较 “危险”的,因为你不知道宏展开后会是什么一个样子。例如下面这个宏:

#define MAX(a, b) a>b?a:b

当我们这样使用宏时,没有什么问题: MAX( num1, num2 ); 因为宏展开后变成 num1>num2?num1:num2;。 但是,如果是这样调用的,MAX( 17+32, 25+21); 呢,编译时出现错误,原因是,宏展开后变成:17+32>25+21?17+32:25+21Woh,这是什么啊?

所以,宏在使用时,参数一定要加上括号,上述的那个例子改成如下所示就能解决问题了。

#define MAX( (a), (b) ) (a)>(b)?(a)b)

即使是这样,也不这个宏也还是有Bug,因为如果我这样调用 MAX(i++,j++); 经过这个宏以后,ij都被累加了两次,这绝不是我们想要的。所以,在宏的使用上还是要谨慎考虑,因为宏展开是的结果是很难让人预料的。而且虽然,宏的执行很快(因为没有函数调用的开销),但宏会让源代码澎涨,使目标文件尺寸变大,(如:一个50行的宏,程序中有1000个地方用到,宏展开后会很不得了),相反不能让程序执行得更快(因为执行文件变大,运行时系统换页频繁)。

因此,在决定是用函数,还是用宏时得要小心。

分享到:
评论

相关推荐

    const #define inline

    在编程领域,`const`、`#define`与`inline`是三个常用的关键字或预处理器指令,它们各自具有独特的作用和使用场景,掌握它们的区别和正确应用是提升代码质量和效率的重要手段。 #### 1. `const`关键字 `const`...

    typedef与define的区别

    从以上的概念可以看出,typedef只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在C中是为了定义常量,到了C++,const、enum、inline的出现使它也渐渐成为了起别名的工具。 typedef和#...

    typedef和define的区别

    从概念上讲,typedef 只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define 原本在 C 中是为了定义常量,到了 C++,const、enum、inline 的出现使它也渐渐成为了起别名的工具。 在实践中,...

    如何区分C++中的inline和#define宏

    #define ABS(x) ((x)>0? (x):-(x)) 当++i出现时,宏就会歪曲我们的意思,换句话说就是:宏的定义很容易产生二意性。  (3)为什么inline能取代宏? 1、 inline 定义的类的内联函数,函数的代码被放入符号表中,在...

    宏(#define)定义函数妙用

    在C/C++编程中,宏定义(#define)是一种预处理器指令,用于创建符号常量或简单的文本替换。宏在程序编译时起作用,它不是真正的函数,但可以通过模拟函数调用来实现类似的功能,从而提高代码的可读性和可维护性。在...

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

    内联函数和宏定义在C语言中都是用来优化程序性能的工具,但它们在使用上有着本质的区别。内联函数提供了更加安全和可调试的代码替代宏定义,尤其是在需要兼顾性能和代码可读性的场景下。 内联函数是C++引入的概念,...

    常用宏定义#define

    在C/C++编程语言中,`#define` 是预处理器指令,用于创建宏定义,它在...因此,在使用宏定义时,需谨慎处理,尤其是在处理复杂表达式和函数宏时,应尽量考虑使用inline函数或者C++11引入的 constexpr 关键字来替代。

    c++ 尽量不要使用#define 而是用const、enum、inline替换。

    例如:这里程序文件开头有如下#define语句 代码如下: #define N 10 #define PI 3.14 #define MAX 10000 #define Heigth 6.65 … … 假设这里程序运行出错误,而且就是在我们使用这些常量有错误,此时编辑器应该会抛...

    typedef和#define的用法与区别

    typedef和#define的用法与区别 一、typedef的用法 在C/C++语言中,typedef是一种语言编译过程中的一部分,它常用来定义一个标识符及关键字的别名。它并不实际分配内存空间,实例像:typedef int INT;typedef int ...

    C语言编程技巧 关于const和#define的区别心得

    在C语言编程中,`const`关键字和`#define`预处理器宏是两种常见的常量定义方式,但它们之间存在显著的区别。理解这些差异对于编写更高效、更可维护的代码至关重要。 首先,`const`关键字是C语言的正式组成部分,它...

    iOS静态inline hook

    #define original_function hooked_function ``` #### 3.3 第三方库 第三方库如FLEX或Reveal,它们提供了更高级的接口和自动化流程来实现静态内联HOOK。 ### 4. 应用场景 静态内联HOOK在iOS开发中有多种用途: ...

    #define,const,typedef三者联系与区别

    typedef 只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在 C 中是为了定义常量,到了 C++,const、enum、inline 的出现使它也渐渐成为了起别名的工具。 typedef 和 #define 的区别...

    MDK5 宏定义CC_ARM

    #define __INLINE __inline /*!< inline keyword for armcc */ #elif defined ( __ICCARM__ ) #define __ASM __asm /*!*/ ``` 这里定义了与编译器相关的宏: - `__CC_ARM`:表示使用的是ARM的编译器(armcc),...

    C++中inline函数详解

    C语言中的宏定义:#define ExpressionName(var1,var2) (var1+var2)*(var1-var2)这种宏定义,它使用预处理器实现,没有了参数压栈、代码生成等一系列得到操作,因此效率很高。但缺点如下: 仅仅是做预处理器符号表中...

    C++与操作系统等面试题39

    ##### 1.3 `define` 与 `inline` 的区别 - **定义性质**:`#define` 是宏定义,而 `inline` 是函数的一种属性。 - **处理时机**:`#define` 在预处理阶段进行文本替换,而 `inline` 在编译阶段进行函数体的内联替换...

    Linux c中define的用法小结

    - 在某些情况下,`const`关键字和 inline 函数可能是更好的选择,因为它们提供类型检查和更高效的代码。 了解这些基本的`#define`用法,有助于编写更加高效且易于维护的C语言代码。在编写涉及宏的代码时,一定要...

    cpp代码-#define 宏替换的使用??

    在C++编程中,`#define` 是预处理器指令,用于定义宏,它在编译时进行文本替换,是C++中的一个基础特性。本文将深入探讨`#define` 宏替换的使用,以及它在实际开发中的作用和注意事项。 首先,`#define` 用于创建一...

Global site tag (gtag.js) - Google Analytics