0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

详细解析内联函数以及在C语言中的作用

5RJg_mcuworld 2017-12-21 14:21 次阅读

内联函数的作用

内联函数是一种编译机制,优点从代码上是看不出来的,但是程序的执行效率上有差别,通常,编译器对函数调用的处理是一种类似中断的方式,即当执行到函数调用语句时,程序把当前所有的状态信息比如CPU所有寄存器(其中一个很重要的就是指令指针寄存器)的值保存起来,然后放心大胆地转去执行那个函数的代码,执行完后再返回原来的地方,恢复原先保存过的状态信息,于是也就可以接着原来被中断的指令继续往下执行。

这样,就很容易实现代码的结构化,因为可以把一些独立的功能模块写成函数,函数内部的变量和外部的变量互不影响,而且函数执行完后就可以释放这个函数内部变量的所使用的内存空间(这就是为什么函数退出后,其内部变量不再有效),对内存的使用也是很经济的(否则,如果一个大的程序全部由一个函数组成,那么所有的变量都得自始至终地占用内存空间),当然,还有其他优点,比如可以实现递归,总之是好处多多。

可是,任何事情往往都有两方面,这样做虽然好处多多,但也是有代价的,那就是前面所说的,任何一次函数调用,程序都得进行保存和恢复状态信息的动作,用数据结构的术语说就是进栈和退栈,当然,还有内存分配的过程,如果函数的代码非常少,这种代价并不是可忽略的,比如说,你编写一个类,里面有个记录状态的成员变量:

Class MyClass

{

private:

int m_iState;

}

按照面向对象的思想,函数的属性应尽量的私有化,但外部怎么获得这个属性值呢?一般的方法就是加一个共有函数,这就实现的面向对象思想中所谓“通过公用接口操作对象的私有属性”。于是就变成了:

Class MyClass

{

public

int GetState();

private:

int m_iState;

}

int MyClass::GetState()

{

return m_iState;

}

这样一来,面向对象思想倒是体现出来了,但你的CPU会恨你:“你丫一个鸟函数就返回一个整数却让老子进一次栈、弹一次栈”,内存也会埋怨:“兄弟也得跟着分配内存!”

但对你来说,也很委屈,怎么办,把所有的属性都改成public?让外部内码直接访问?况且,那样也不解决所有问题,因为有时候即使不是为了面向对象,我们也需要把独立的功能模块做成函数,比如说产生随机数的函数。我想

int iRand=rand();

总比:

int iRand=((int)(MULTIPLIER * Seed + INCREMENT)》》16)&0x7fff;

看起来舒服吧?(我这里只是打个比方,VC的rand函数并不是内联函数)

而内联函数就是解决这个问题了,对于程序员,他还是把独立功能写成函数的形式,但只要声明为内联,编译器就不把它编译成一次函数调用,而只是类似于把函数的代码拷贝到被调用的地方,而且这完全是编译器私下里完成的,原来的访问权限等问题丝毫不受影响。这不是两全齐美了吗:在保证代码的面向对象性和结构化不受损失的条件下,程序的效率也没有损失,比如上面那个类,就变成了:

Class MyClass

{

public:

inline int GetState();

private:

int m_iState;

}

int inline MyClass::GetState()

{

return m_iState;

}

有一点要注意,内联函数要跟类的声明写在同一个文件中,否则编译会出错。按照VC管理源文件的风格来说,就是内联函数最好写在声明类的.h文件中,而不是像一般函数那样写在实现类的.cpp文件中。

当然,内联函数还有另外一种写法,就是直接写在类中,此时,不必使用“inline”关键字。

Class MyClass

{

public:

int GetState(){ return m_iState; }

private:

int m_iState;

}

最后,还要注意,内联函数只是一种编译机制,用上面两种形式声明的函数仅仅是建议编译器进行内联,而编译器是否内联不一定。正如前面所说,函数调用的开销只是对小的函数不可忽略,对于重量级的函数还是可以忽略的,而且在绝大多数的场合,函数调用才是人间正道,才是解决问题的最佳。所以大多数编译器并不把带有循环、递归等或者代码比较多的函数进行内联编译,有的甚至不允许声明成内联的。

C语言的内联函数的作用

[cpp] view plain copy关内联函数键字inline

[cpp] view plain copyvoid myprintf(int a)

{

priintf(“%d”,a);

}

int main()

{

for(i=0;i《100;i++)

myprintf(3);

}

对于这个函数,在进行反复的打印3的过程中我们是不是要反复的调用myprintf(int a)这个函数,进函数和出函数是需要时间的,假设这个过程用时为4ms,而执行printf这个操作只需要2ms,那么在100次循环的过程中进出函数的时间比函数功能printf需要的时间还要长,这样很影响工作效率。于是,我们就想要如何去免去进出函数的过程呢?那么就可以声明inline这个关键字,有何用途?当我们声明了一个inline的函数时候,函数被调用的语句就被替换成了函数本身,进行了一个预处理

[cpp] view plain copyint main()

{

for(i=0;i《100;i++)

void myprintf(3)

{

printf(“%d”,3);

}

return 0;

}

这样一来我就非常明显的知道这个函数是干什么的了,就不需要去调用函数的定义部分,再通俗点讲,原来我要从家里去外面的商店去买冰淇淋(来回需要时间),现在商店就在我家里面了,那么我是不是省去了去商店的时间呢?但是相应的我这个家要很大(也就是所谓的空间要很大才能包含这个商店对吧?)这样就是用空间去换取了时间了。

内联函数在编译层面类似于宏替换。也就是说,程序执行过程中调用内联函数不需要入栈出栈,所以效率会提高。

[cpp] view plain copy#include《stdio.h》

inline int add(int x, int y)

{

return x+y;

}

int main()

{

int i,j,k;

printf(“请输入两个整数的值:”);

scanf(“%d%d”,&i,&j);

k=add(i,j);

printf(“k=%d\n”,k);

return 0;

}


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7597

    浏览量

    136138
  • 内联函数
    +关注

    关注

    0

    文章

    10

    浏览量

    2200

原文标题:内联函数在C语言中的作用

文章出处:【微信号:mcuworld,微信公众号:嵌入式资讯精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言中的socket编程基础

    数据 步骤6:关闭socket 创建socket C语言中,创建socket需要使用socket()函数。这个函数需要两个参数:域
    的头像 发表于 11-01 16:51 236次阅读

    C语言指针详细解析

    可以对数据本身,也可以对存储数据的变量地址进行操作。 指针是一个占据存储空间的实体在这一段空间起始位置的相对距离值。C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是
    发表于 09-14 10:03

    内联函数定义 为什么需要内联函数

    inline关键字是C99标准的型关键字,其作用是将函数展开,把函数的代码复制到每一个调用处。
    的头像 发表于 02-19 12:20 515次阅读

    枚举有多大?c语言枚举end的作用是什么?

    枚举有多大?c语言枚举end的作用是什么? 枚举C语言中是一种常见的数据类型,用于定义一组相互
    的头像 发表于 01-19 14:19 562次阅读

    如何解决C语言中的“访问权限冲突”异常?C语言引发异常原因分析

    如何解决C语言中的“访问权限冲突”异常?C语言引发异常原因分析  C
    的头像 发表于 01-12 16:03 5037次阅读

    C语言中结构体能不能相加

    C语言中,结构体能不能相加?
    的头像 发表于 12-19 17:04 1208次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言中</b>结构体能不能相加

    如何给C语言中函数定义两个不同的名字?

    最近有位哥问我,如何给C语言中函数定义两个不同的名字?就是这两个名字都是指向同一个函数,同一个地址,而且两个名字都可以当做函数来用的那种。
    的头像 发表于 12-19 16:21 756次阅读

    c语言中逻辑真等价于什么

    C语言中,逻辑真等价于1。逻辑真可以理解为一个表达式、语句或条件的结果为真,即满足条件。计算机科学和编程中,逻辑真控制流语句、循环和条
    的头像 发表于 11-30 14:10 1994次阅读

    c语言中decimal的含义

    C语言中的“decimal”是一种数据类型,用于表示十进制数字。C语言中,常用的数据类型有整数类型(int)、浮点类型(float和dou
    的头像 发表于 11-30 10:57 2284次阅读

    c语言中a++是什么意思

    C语言中,a++是一个自增运算符,用于对a的值进行自增操作。它是一个简化的表达式,相当于将a的值加1,并返回自增前的值。 C语言中,自增运
    的头像 发表于 11-26 09:19 1.8w次阅读

    c语言中函数函数体用什么符号括起来

    函数 是指将一组能完成一个功能或多个功能的语句放在一起的 代码结构 。 C语言程序 中,至少会包含一个函数,及主
    的头像 发表于 11-24 15:52 667次阅读
    <b class='flag-5'>c</b><b class='flag-5'>语言中</b><b class='flag-5'>函数</b>的<b class='flag-5'>函数</b>体用什么符号括起来

    c语言源程序main函数的位置

    C语言源程序中的main函数是程序的入口点,它被认为是C语言程序的起点。执行程序时,操作系统将
    的头像 发表于 11-24 10:23 2312次阅读

    c语言中数组怎么定义

    C语言中,数组是一种用来存储相同类型元素的数据结构。它可以存储多个元素,并通过一个共同的名称来引用这些元素。数组是一种很重要的数据结构,可以用于解决很多实际的问题。 C
    的头像 发表于 11-24 10:11 2916次阅读

    c语言gets函数可以输入数字吗

    C语言中的gets函数是用来读取字符串的,而不是用来读取数字的。它会读取输入的字符直到遇到换行符或者文件结束符。因此,如果你尝试使用gets函数来读取数字,是无法准确获取数字本身的。
    的头像 发表于 11-24 10:00 1452次阅读

    \0c语言中怎么用

    是由贝尔实验室的Dennis Ritchie为了开发UNIX操作系统而设计的。它在20世纪70年代初首次出现,并迅速流行起来。C语言以其简洁、高效、低级别的特性成为了广泛使用的编程语言。 二、基本语法 注释
    的头像 发表于 11-24 09:59 3007次阅读