首页 > 编程笔记 > C语言笔记

C语言函数的定义和使用(超级详细)

在数学中,函数是一个常见的术语,如下图所示。然而,编程语言中的函数与数学中的函数有着本质的区别。


图 1 正态函数

在编程中,函数就像是一个工具箱,可以把常用的动作或任务放进去,在需要时调用(或使用)工具箱中的内容。例如,如果你经常需要计算两个数字的和,则可以把这个任务放入一个名为“计算和”的工具箱中,当你需要计算和时,只需调用这个工具箱。

一个函数具备以下三个基本特性,如下图所示。


图 2 函数的基本特性
  1. 开始执行任务时,函数可以接收一些输入值。
  2. 在执行任务的过程中,函数可以执行一些操作。
  3. 执行任务完成后,函数可以返回一些值。

以 main() 主函数为例,下图显示了这三个基本特性分别对应于主函数的哪个部分。


图 3 主函数的基本特征解析

在图中,我们可以看到主函数是如何对应以上三个基本特性的:
  1. main() 函数后面的括号是用于接收输入值的。
  2. printf 语句是主函数执行的任务。
  3. return 语句是主函数需要返回的值。

下图显示了主函数具体完成哪些任务。


图 4 函数完成的任务
  1. 主函数后面的括号中为空,表示主函数没有接收到任何输入值。
  2. 主函数的任务是向屏幕输出一行字符串。
  3. 主函数返回数字 0。

在了解了函数的三个基本特性之后,我们可以通过主函数进一步分析函数的其他部分。
  1. 其中,int 表示函数的返回值类型为整数类型,int 是 integer(整数)的缩写。这是由语言标准规定的,不能用其他单词代替。
  2. main 是函数名,其后的括号 ( ) 表示输入参数,目前为空。
  3. return 后面跟的是函数的返回值,此处为 0。0 是一个整数,对应于函数名前的 int。

根据以上分析,可以总结出编写函数的公式。
返回值类型 函数名(输入参数值)
{
    函数执行具体操作
    return 函数返回值;
}
用花括号括起来的内容被称为函数体。注意,函数体必须用花括号括起来,不能省略。花括号上面的内容,包括函数名、函数参数和返回值,被称为函数头。函数头与函数体如下图所示。


图 5 函数头与函数体

函数的定义

在学习了函数的概念和写法之后,我们可以通过编写一个计算两个整数相加的函数来加深对函数概念的理解。这个函数需要实现输入两个整数,并返回它们相加的结果。

由于我们的函数用于计算加法,因此可以将函数命名为 add。当然,自定义函数的名称可以根据个人喜好进行编写,即使将函数命名为 aaaaa 也是可以的。但是,为了让函数名称具有语义,方便人们阅读和理解,我们通常使用具有特定含义的英文单词作为函数的名称。

下面的实例程序展示了实现两个整数相加的函数的定义。这段代码被称为 add 函数的函数定义。
//  这段代码被称为add函数的函数定义
int add(int a, int b)
{
    return a + b;
}
下图展示了 add 函数的解析,它完全符合前面所述的函数的三个特性。


图 6 add函数的解析

这里还需要重点关注括号内的函数参数。在 C语言中,函数参数的书写方式如下:

函数的调用

前面定义了一个名为 add 的函数,但是我们怎样才能使用它呢?add 函数可以直接运行吗?

显然,add 函数是无法直接运行的。在大多数 C语言程序中,主函数是程序的入口,它是程序执行的起点。在主函数中,可以调用其他函数,并通过它们执行不同的任务。只有单独的 add 函数是无法正确运行的,因此需要在主函数中调用 add 函数才能得到正确的结果。

需要注意的是,一个 C语言项目中只能存在一个 main 函数,如果一个项目中存在多个源文件,并且每个源文件中都有一个 main 函数,则编译时将会报错。如在 Visual Studio 中会出现“fatal error LNK1169: 找到一个或多个多重定义的符号”错误。

现在稍微修改代码,在主函数中调用 add 函数,具体的代码如下:
#include <stdio.h>
int add(int a, int b)
{
    return a + b;
}
int main()
{
    int result;
    result = add(2, 3);
    printf("%d", result);
    return 0;
}
下面分析程序是如何运行的:

错误的调用方式

在 C语言中,编译器会按照从上往下的顺序阅读代码,因此我们需要在 main 函数中调用 add 函数之前定义 add 函数。编译器从代码开始,看到函数定义描述了一个名为 add 的函数。接下来,编译器发现在 main 函数中需要使用 add 函数。编译器由于已经知道了 add 的定义,因此可以正常编译。

函数定义在函数调用前如下图所示。


图 7 函数定义在函数调用前

如果将函数定义和函数调用的顺序反过来,编译器就无法理解 add 究竟是什么,导致报错并停止编译。

函数定义在函数调用后如下图所示。


图 8 函数定义在函数调用后

声明:《C语言系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。