۞ 外部函数与内部函数

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

 

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

۞ 外部函数

什么是外部函数呢?当我们在开发大型项目时,为了便于团队的协同工作,往往需要把一个项目拆分成很多源文件来分别实现,最终再把它们整合在一起。为了减少重复代码,一个源文件有时需要调用其他源文件中定义的函数。所以,在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++编程学习基地,【点击进入】!

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

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

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

 

 

【C语言编程入门笔记】C语言果然博大精深!函数还分内部和外部?的更多相关文章

  1. 【C语言编程入门笔记】排序算法之快速排序,一文轻松掌握快排!

    排序算法一直是c语言重点,各个算法适应不用的环境,同时,在面试时,排序算法也是经常被问到的.今天我们介绍下快速排序,简称就是快排. 1.快速排序思想: 快排使用 分治法 (Divide and con ...

  2. OpenCV3编程入门笔记(2)计时函数、感兴趣区域RIO、分离/混合通道

    11     绘制直线的line函数 DrawLine(Mat img, Pont start, Point end); 绘制椭圆的ellipse函数 DrawEllipse(Mat img, dou ...

  3. go语言学习入门篇1---go语言的主要特性与发展

    1.1 影响 Go 语言发展的早期编程语言 正如 "21 世纪的 C 语言" 这句话所说,Go 语言并不是凭空而造的,而是和 C++.Java 和 C# 一样属于 C 系.不仅如此 ...

  4. Linux C语言编程学习笔记 (1)进程控制入门

    想进行Linux系统开发已经很久了,一直没有付诸实践.今日终于开始学习Linux下的C语言编程,研究一天,终于大概弄明白了Linux系统进程管理的一些基本概念和编程方法,总结下来以方便大家学习和自己实 ...

  5. linux 操作系统下c语言编程入门

    2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门--时间概念 5)Linux程序设计入门--信号处理 6)Linux程序设计入门--消息管理  ...

  6. C语言编程入门之--第四章C语言基本数据类型

      导读:C语言程序中经常涉及一些数学计算,所以要熟悉其基本的数据类型.数据类型学习起来比较枯燥,不过结合之前的内存概念,以及本节的字节概念,相信数据类型也就不难理解了.本章从二进制的基本概念开始,然 ...

  7. C、C++、Java到Python,编程入门学习什么语言好?

    摘要:回顾编程语言几十年来的兴衰起伏,似乎也折射了整个信息产业的变迁消亡,想要在技术的洪流里激流勇进,找准并学精一两门编程语言更加显得至关重要. 最近,TIOBE更新了7月的编程语言榜单,常年霸榜的C ...

  8. 编程入门选什么语言好?C 语言还是Python ?为你解析

    前面我分享过计算机行业已经成了学校选择排名第一,家长和学生都很看好计算机类专业.现在IT行业也越来越火爆,程序员越来越被人看好.面对相比同龄人高薪资的诱惑,人们很难不心动,即使秃头也值得! 那么问题来 ...

  9. [Java入门笔记] Java语言简介

    前言 学习Java有一段时间了,但是一直缺少一个系统的思想,现在重新通过书籍中.网上的文章,视频等资料,整理与回顾Java的知识点. 言归正传,让我们先从了解Java语言开始. Java语言的由来 J ...

随机推荐

  1. Intersection of Two Prisms(AOJ 1313)

    原题如下: Suppose that P1 is an infinite-height prism whose axis is parallel to the z-axis, and P2 is al ...

  2. oracle之三存储库及顾问框架

    AWR存储库及顾问框架(PPT-I-349-360) 14.1 Oracle数据库采样ASH和AWR. 1) ASH(Active Session History) ASH收集的是活动会话的样本数据, ...

  3. CTF-Bugku-杂项-21-28

    2020.09.14 下午奥力给 做题 第二十一题 细心的大象 https://ctf.bugku.com/challenges#细心的大象 这一看就是一只有故事的大象,图片详情中有东西,base64 ...

  4. Vue axios封装 实现请求响应拦截

    封装 axios.js import axios from 'axios' import { baseURL } from '@/config' class HttpRequest { constru ...

  5. RXJAVA源码之多线程

    在不指定线程的情况下, RxJava 遵循的是线程不变的原则,即:在哪个线程调用 subscribe(),就在哪个线程生产事件:在哪个线程生产事件,就在哪个线程消费事件.如果需要切换线程,就需要用到 ...

  6. Druid实现数据库连接用户密码加密

    使用ConfigFilter ConfigFilter的作用包括: 从配置文件中读取配置 从远程http文件中读取配置 为数据库密码提供加密功能 1 配置ConfigFilter 1.1 配置文件从本 ...

  7. @Autowried入门和源码分析

    话不多说直接上代码: 声明一个接口userDao: package ioc.hello; public interface UserDao { public void test(); } 2个实现类: ...

  8. 关于excel表格中只复制筛选后的数据

    今天笔者在整个一个表格中的数据,需要将原表格的数据根据一些条件筛选后,整理到新的excel表中 但是发现每次操作,都将筛选条件之外的数据也粘贴进去了,但笔者确实又只选中了部分数据 经过多种方式尝试后, ...

  9. O、Θ、Ω&主定理

    1.这些是时间复杂度的.(e.g. O(n).Θ(n).Ω(n)) 主要为主定理(坏东西) 2.本质 O <= Θ = Ω >= 3.(你可以把他们都试一遍)主要用处(目前,2020-09 ...

  10. 我要吹爆这份阿里中间件技术内部的RM笔记,简直佩服到五体投地

    消息队列 RocketMQ 版是阿里云基于 Apache RocketMQ 构建的低延迟.高并发.高可用.高可靠的分布式消息中间件.该产品最初由阿里巴巴自研并捐赠给 Apache 基金会,服务于阿里集 ...