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语言
    +关注

    关注

    183

    文章

    7642

    浏览量

    144599
  • 内联函数
    +关注

    关注

    0

    文章

    10

    浏览量

    2421

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

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

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    C语言的编程技巧

    设计,分层开发代码,便于理解和维护。 ‌8、避免使用GOTO语句‌:尽管GOTO语句某些情况下仍然有用,但现代编程更倾向于使用函数和循环控制结构,以提高代码的可读性和维护性。 ‌9、利用C
    发表于 11-27 06:46

    简单的内联汇编介绍

    这次主要学习了使用内联汇编完成一些较为简单的操作。我们思考接下来程序中插入跳转指令来实现一些想要实现的操作以及对自行设计的硬件进行操作。
    发表于 10-30 08:04

    RISC-V的工具链GCC内联汇编

    具体实现方法和步骤 RISC-V架构中定义的CSR寄存器需要使用特殊的CSR指令进行访问,如果CC++程序中需要访问CSR寄存器,只能使用内嵌汇编指令的方法。
    发表于 10-30 06:59

    第4章 C语言基础以及流水灯的实现(4.3 4.4)

    4.3 C语言基本运算符 小学数学学过加、减、乘、除等运算符号以及四则混合运算,而这些运算符号C语言中
    的头像 发表于 10-29 15:30 178次阅读

    GCC内联汇编

    语言代码中定义的变量,比如demo中定义的“%0、%1”,操作数C语言中总被视为32bit的long型数据,但是像汇编中传递时根据汇编指
    发表于 10-24 07:46

    通过内联汇编调用乘法指令mulh\\mulhsu\\mulhu

    mulh、mulhu与mulhsu指令,不能直接验证,需要其他方法。因此,我们想到了C语言中嵌入内联汇编,分别生成三条指令的接口函数,之后
    发表于 10-24 06:52

    C语言中内联函数与宏

    C编程中,内联函数和宏都用于避免函数调用的开销并编写可复用的逻辑部分,但它们工作方式和安全性
    的头像 发表于 07-25 15:10 1713次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言中</b>的<b class='flag-5'>内联</b><b class='flag-5'>函数</b>与宏

    Windows环境下32位汇编语言中文资料

    电子发烧友网站提供《Windows环境下32位汇编语言中文资料.rar》资料免费下载
    发表于 06-30 15:14 0次下载

    MSP430常用内联函数说明

    电子发烧友网站提供《MSP430常用内联函数说明.docx》资料免费下载
    发表于 06-05 17:20 0次下载

    深入理解C语言C语言循环控制

    改变程序的执行流程,使代码更加灵活和可控。本文将详细介绍这些语句的作用及其应用场景,并通过示例代码进行说明。Part.1break语句C语言中break语句有两种
    的头像 发表于 04-29 18:49 1733次阅读
    深入理解<b class='flag-5'>C</b><b class='flag-5'>语言</b>:<b class='flag-5'>C</b><b class='flag-5'>语言</b>循环控制

    C语言中结构体与联合体的深度解析:内存布局与应用场景

    一、基础概念与核心差异 1.1 结构体(Struct)的本质 **结构体是C语言中实现数据封装的基石,其核心特征在于内存独立性。每个成员变量在内存中按声明顺序依次排列,形成连续的内存块。以学生信息为
    发表于 04-08 09:18

    ​VLM(视觉语言模型)​详细解析

    详细解析: 1. 核心组成与工作原理 视觉编码器 :提取图像特征,常用CNN(如ResNet)或视觉Transformer(ViT)。 语言模型 :处理文本输入/输出,如GPT、BERT等,部分模型
    的头像 发表于 03-17 15:32 7571次阅读
    ​VLM(视觉<b class='flag-5'>语言</b>模型)​<b class='flag-5'>详细</b><b class='flag-5'>解析</b>

    EE-32:语言扩展:内存存储类型、ASM和内联构造

    电子发烧友网站提供《EE-32:语言扩展:内存存储类型、ASM和内联构造.pdf》资料免费下载
    发表于 01-14 15:03 0次下载
    EE-32:<b class='flag-5'>语言</b>扩展:内存存储类型、ASM和<b class='flag-5'>内联</b>构造

    EE-62:C语言中访问短字内存

    电子发烧友网站提供《EE-62:C语言中访问短字内存.pdf》资料免费下载
    发表于 01-07 14:02 0次下载
    EE-62:<b class='flag-5'>在</b><b class='flag-5'>C</b><b class='flag-5'>语言中</b>访问短字内存

    EE-128:C语言中的DSP:从C调用汇编类成员函数

    电子发烧友网站提供《EE-128:C语言中的DSP:从C调用汇编类成员函数.pdf》资料免费下载
    发表于 01-07 13:48 0次下载
    EE-128:<b class='flag-5'>C</b><b class='flag-5'>语言中</b>的DSP:从<b class='flag-5'>C</b>调用汇编类成员<b class='flag-5'>函数</b>