۞ 外部函数与内部函数

前面我们讲解了关于函数的调用都是针对同一个源文件中其他函数进行调用的,而在有些情况下,函数也可以对另外一个源文件中的函数进行调用。当一个程序由多个源文件组成时,根据函数是否能被其他源文件调用,可以将函数分为内部函数和外部函数两种类型。

 

出于大家可能不了解,我就画了一个程序运行的简图。大家可能会很奇怪,怎么会有多个源文件,一般我们都是只创建一个源文件,然后在里面写代码的。事实上我们可以创建多个源文件,用来把各个功能模块区分,所以我们是可以在一个源文件中调用另一个源文件中的函数的。

۞ 外部函数

什么是外部函数呢?当我们在开发大型项目时,为了便于团队的协同工作,往往需要把一个项目拆分成很多源文件来分别实现,最终再把它们整合在一起。为了减少重复代码,一个源文件有时需要调用其他源文件中定义的函数。所以,在C语言中,可以被其他源文件调用的函数称为外部函数。

另外在调用外部函数之前,需要在当前源文件中定义外部函数。定义外部函数的方式是在函数的返回值类型前面添加extern关键字,示例代码如下:

 

在这个示例代码中,编译器会通过 extern 关键字知道 add() 函数是定义在其他文件中的外部函数。

为了让大家能够掌握外部函数的用法,接下来,在 first.c 文件中定义一个 add() 函数,然后在 second.c 文件中使用 first.c 文件中定义的 add() 函数。

first.c

second.c

 

运行结果如图所示:

在 second.c 文件中,second.c 文件通过调用 first.c 中定义的 add() 函数计算出1加2的结果。second.c 文件中的外部函数 add() 是在 first.c 文件中实现的,编译器从 first.c 中找到了该函数,并将它的作用域扩大到 second.c 文件中,于是 second.c 文件中也可以调用这个 first.c 中定义的add() 函数,从而完成计算。

为简化编程,C语言中允许在定义外部函数时省略extern 关键字。first.c 中定义的外部函数 add() 也可以修改为下面的代码:

 

上述代码由函数的返回类型、函数名和参数列表组成,这类格式的代码被称为函数原型。当代码中包含函数原型时,可能会有下列两种情况:

1、程序员希望编译器自动从其他文件中查找该函数的定义。

2、程序员先定义未实现的空函数,然后在其他文件中具体实现。

接下来就来看一下printf()函数的原型写法,具体代码如下:

 

当在 main()函数中定义了 printf()函数的原型后再调用时就可以不用包含头文件 。

 

运行结果如图所示:

 

在这个例题中,我们的程序并没有包含头文件 stdio.h ,但是在代码第1行中声明了 printf()函数的原型,那么编译器将会根据该原型自动从其他文件中查找该函数的定义,并将该函数的作用域扩展到原型所在的文件中,因此在本文件中就可以调用printf()函数。

需要注意的是,在声明外部函数时,无论有或没有关键字extern,外部函数与原函数定义的返回值类型、函数名称和参数列表必须一致。

۞ 内部函数

从上面讲解的外部函数可知,只要声明一个函数原型就能够调用其他源文件中的函数。但是当多人参与开发一个项目时,很有可能会出现函数重名的情况,这样,不同源文件中重名的函数就会互相干扰。此时,就需要一些特殊函数,这些函数只在它的定义文件中有效,该类函数称为内部函数。

在定义内部函数时,需要在函数的返回值类型前面添加 static 关键字(又称为静态函数),示例代码如下:

为了让大家熟悉内部函数的作用,接下来通过在两个源文件中定义同名的内部函数来演示内部函数的用法。

first.c

 

second.c

 

运行结果如图所示:

 

在 first.c 和 second.c 中,我们都定义了一个函数 show(),second.c文件中的函数是内部函数。从运行结果可以看出,first.c中的show()函数被调用成功了,因此说明内部函数只会被自身调用,不会受到其他文件中同名函数的影响。从运行结果中可以看出,second.c中的show()函数被调用了。

M脚下留心:

如果将second.c中修饰show()函数的关键字static去除,运行时程序会提示错误,如下图所示:

 

从这张图的错误结果可以看出,如果outer.c中的show()函数不声明为内部函数,就会受到其他文件中的同名函数的干扰。

学计算机编程不易,此路应携手前行。

如果你也想学计算机编程的话!

可以来我的C语言/C++编程学习基地,【点击进入】

还有免费(零基础教程,项目实战教学视频)!

涉及:游戏开发、课程设计、常用软件开发、编程基础知识、黑客等等...

和志同道合的小伙伴们一起学编程吧!

 

 

最新文章

  1. lvs+keepalived
  2. PHP知识库图谱汇总(完善中)
  3. build path功能详解
  4. mysql的时间函数
  5. EXTJS 3.0 资料 控件之 FormPanel 插入button用法
  6. 《JavaScript核心概念》基础部分重点摘录
  7. 转:Node.js邮件发送组件- Nodemailer 1.0发布
  8. 每天进步一点点-->功能fseek() 使用方法
  9. 利用LinkedList实现洗牌功能
  10. iOS开发——Xcode快捷键
  11. 【魅族Pro7】——BootStrap/JQuery/Canvas/PHP/MySQL/Ajax爬坑之项目总结(一)
  12. Material使用03 MdCardModule模块、MdInputModule模块
  13. Linux下用程序实现统计cpu和内存的利用率
  14. 第一次提交 nacos 代码
  15. ReactiveCocoa的学习内容
  16. Python处理word文件
  17. HDU 5950 Recursive sequence(矩阵快速幂)
  18. html : 九宫格(响应式)
  19. windows无法安装到这个磁盘。选中的磁盘采用GPT分区形式 Windows 检测到 EFI 系统分区格式化为 NTFS。将 EFI 系统分区个数化为 FAT32,然后重新启动安装
  20. ASP.NET项目在IIS上使用虚拟目录

热门文章

  1. css常用属性之display属性
  2. 一次MySQL索引失效引发的思考
  3. Spring Boot 如何使用拦截器、过滤器、监听器?
  4. 在CentOS Linux 7.5上安装MySQL
  5. xss小游戏通关
  6. Java Comparable 和 Comparator 接口详解
  7. Centos-显示目录或者目录下文件信息-ls
  8. PCA基本原理
  9. 给select赋值的一种方法
  10. 手把手教你AspNetCore WebApi:增删改查