我是靠谱客的博主 魁梧玫瑰,最近开发中收集的这篇文章主要介绍【C++】四、inline函数、C/C++相互调用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录:

    • 一、inline函数
      • (一)inline函数的概念
      • (二)inline函数 && 宏
      • (三)inline函数 && static
      • (四)inline函数 && 普通函数
      • (五)内联函数的缺点及使用建议
      • (五)内联函数的限制
    • 二、C/C++相互调用
      • (一).cpp文件中调用.c文件中的函数
      • (二).c文件中调用.cpp文件中的函数
        • 1. .cpp源文件允许修改
        • 2. .cpp源文件不允许修改

一、inline函数

(一)inline函数的概念

用关键字inline修饰的函数,称为inline函数即内联函数。inline内联函数,在编译阶段,以独立的函数单元编译展开,在调用点直接代码展开,不会(没有必要)生成函数符号,故只有本文件可见

我们可以通过一段代码来感受一下内联函数的概念:
在这里插入图片描述
可以看到:

  • 不加内联inline关键字,在定义点将sum函数符号放在函数的.text区,在运行时在*UND*放的声明点的函数符号可以找到一样的函数符号,所以解析成功。
  • 加了内联 ,sum函数直接在sum.cpp里面直接展开,不会生成函数符号,那么sum声明点的函数符号无法解析,程序会出错。所以内联函数只有本文件可以用,其他文件不能使用,因为没有函数符号,无法连接到。

(二)inline函数 && 宏

inline内联函数是直接展开在调用点,宏替换也是直接展开替换,那么它们的区别?

  • 宏在预编译处理,直接文本替换,无任何检查
  • 内联函数在编译阶段处理,有类型检查和安全检查。所以内联函数是安全的。故可以说内联函数是一种更安全的宏。

(三)inline函数 && static

inline内联函数只能本文件可见,static修饰的函数也是本文件可以使用,那么它们有什么区别呢?

  1. 内联在调用点直接代码展开,不需要开栈清栈static修饰的函数,有开栈和清栈的开销
  2. 内联不需要生成符号static需要生成符号,将符号从 global(全局,项目下所有的文件可见)变为local(只有本文件可以见)。

(四)inline函数 && 普通函数

  • 普通函数的调用在汇编阶段,需要push压实参指令,call指令调用函数等一系列指令,给函数开辟栈帧,函数运行完成,有函数退出栈帧的过程。
  • 内联函数在编译阶段,在函数的调用点将函数的代码展开,省略了函数栈帧开辟回退的调用开销,效率比较高。
  • 在debug版本下,内联函数不生效,和普通函数一样,有开栈清栈的过程。

(五)内联函数的缺点及使用建议

内联的效率高,直接代码展开,没有清栈开栈的开销,那么为啥不把所有的函数默认处理为内联函数呢?

如果 内联函数代码过多,那么只要使用内联函数的代码就会变得很庞大,这就是以代码膨胀为代价,以空间换时间的概念。所以内联函数如果代码过多就会导致空间和时间效率都变低

所以内联 使用建议

  1. 如果函数执行的开销<函数开栈清栈的开销,表示函数体简单,那么建议设置为内联函数
  2. 如果函数指向开销>函数开栈清栈的开销,那么表示函数体复杂,不建议设置为内联函数

(五)内联函数的限制

  1. 内联只在Release版本生效,debug版本不生效,和普通函数一样,有入栈退栈的过程。
  2. inline只是给编译器的一个建议,是否会处理为内联函数,还是编译器根据当前的代码结构判断 ,一般递归、循环、分支switch编译器不会把它们处理成内联的。
  3. inline是基于实现的,不是基于声明的。 如果你写到声明点上,声明点展开啥也没有,所以编译器不会处理,它只会去处理在函数定义点的内联。
  4. 内联的实现要写在头文件.h中,如果写在源文件中,没有调用点,那么无法展开,其他文件有调用点无法使用。只有写在头文件,被包含在其他文件中,在预编译阶段展开后,那么当前源文件中就会出现内联函数的定义,如果有调用点直接调用即可。

二、C/C++相互调用

在一个很大的项目中,可能会有.c文件,.cpp文件,那么c函数可以在.cpp中调用吗,.cpp里的函数可以在.c中调用吗?我们看一下面一段代码,sum.c中有sum函数,main.cpp中声明sum函数,进行调用:

在这里插入图片描述

如果我们不做任何处理,肯定是无法调用的,原因很简单,C,C++生成函数符号的规则不同,定义点和调用点的函数符号规则不同,在链接时,无法进行符号重定位,会失败,然后报错

C/C++无法相互调用的原因是符号生成规则不一样,为了解决这个问题,我们可以让C++代码以C的规则生成函数符号,这样就可以解决问题。那么有两种情况:

(一).cpp文件中调用.c文件中的函数

可以让C++函数声明点采取C的规则生成函数符号,使用 关键字extern "C"

 extren "C"
 { 
	CODE
 }

将C++文件中C函数的声明包含,表示使用C的处理规则。那么上面的代码可以改为:

 extren "C"
 { 
	int sum(int a,int b);//函数符号为_sum
 }

含义就是这里面代码的处理方式以C的规则来处理。这样生成规则就会一样,符号解析成功,不会报错,调用成功。

(二).c文件中调用.cpp文件中的函数

就是将sum函数定义放到C++,函数声明放到C中,运行一样会失败。那么有没有extern “C++”这个语法,让C按照C++的规则生成函数符号?

答案:没有,因为C语言先出来,都是遵循向前兼容,即C++可以改善C的缺点,C不能未卜先知C++的缺点。所以不可能存在extern “C++”这个规则。

1. .cpp源文件允许修改

当允许修改.cpp源文件时,处理这个问题还是需要使用extern “C",把C++中的定义点都包含在extern “C”,让它以C的规则生成函数符号放在.text段。

总结来说,就是 函数定义点和声明点如果是因为C、C++语言的原因不同,导致函数符号生成规则不同,那么在C++的部分用extren “C“将其全部包含,这样使得函数符号生成规则一致,不出错。

2. .cpp源文件不允许修改

假设现在一种情况,C++代码无法修改,那么如何能让C、C++代码相互调用不出错呢?
程序员自我修养里有一句话,在计算机科学领域,一切不能直接处理的问题,都可以通过加一个中间层来处理。

那么我们可以在C,C++中加一个中间层,进行一个二次包装,如下图所示:
在这里插入图片描述

写个.cpp文件把不能修改的C++函数进行一个调用,这个中间层是我自己加的,那么我当然可以给调用点加个extern “C”,这样C++函数的声明和定义点都是C++规则,但是调用点是C,所以C文件可以使用了,这样C和C++就可以互相兼容了。

加油哦!????。

最后

以上就是魁梧玫瑰为你收集整理的【C++】四、inline函数、C/C++相互调用的全部内容,希望文章能够帮你解决【C++】四、inline函数、C/C++相互调用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部