提要:

  1. 初步讲解C语言的函数的概念和语法

前置知识:

  1. 学习过数学,知道什么是数学的函数
  2. 掌握C语言复合语句的概念

什么是函数

数学意义上的函数

近代定义:给定一个数集A,假设其中的元素为x,对A中的元素x施加对应法则f,记作f(x),得到另一数集B,假设B中的元素为y,则yx之间的等量关系可以用y=f(x)表示,函数概念含有三个要素:定义域A、值域B和对应法则f.

对于各位而言,一定知道函数的概念,简单的讲,就是根据一个特定的值x,对其进行特定的计算过程f,计算出最终的一个结果y,也就是f(x).

注:为了方便后续内容的讲解,此后函数值均使用f(x)而不是y表示!

例如,我们求一个整数的平方,这个运算可以封装成一个函数f(x)=x^2来进行计算,我们传入任意的整数x,最终的结果f(x)仍然是一个整数,其值为x的平方.

C语言中的函数

为什么需要函数

随着程序复杂度的提高,我们不能够将所有的功能/运算过程都堆在一个main函数中,适当地拆分出来,编写为若干子函数,让他们互相配合,共同完成一个庞大的目标.

也就是所谓的"大化小",每个函数都负责一个"小目标",最终将所有函数做的"贡献"合并起来,完成整个程序.

或者,将一个庞大的操作分成若干的几步小操作,依次进行运算,可以使程序更加清晰!

这里涉及到面向过程编程思想,后续会讲解到.

一个C函数的结构

C语言的函数(也包括其他所有支持函数的各种高级语言)这一命名是从数学引申来的,其一般意义和数学函数几乎完全等价,关键都是进行某一种运算.

前面的f(x)=x^2这一函数,使用C语言进行描述,一种写法为:

1
2
3
4
int f(int x){
int y = x * x;
return y;
}

很容易理解,这个函数的名称为f,其接受一个整数x,在函数中计算x*x的值,赋值给一个整型变量y,最后把y的值返回.我们想要使用这个函数也很简单:

1
2
int x=10,x2;
x2 = f(x); // x2 的值为100

我们根据这个例子来对应二者的等价关系:

一个函数的各个部分 数学函数 C语言的函数
f 函数名 函数名
x 自变量 函数参数(形式参数)
f(x) 函数值 调用这个函数,return语句返回的值为函数值
x为整数 自变量的定义域(x为整数) 形参x的类型(为int)
返回的函数值为整数 因变量的值域(y/f(x)为整数) int f(int x)中的第一个int,代表这个函数的返回值类型
执行的运算 对应法则f 函数体{}中的语句构成的代码块,依次执行

我们可以很容易地看出两者之间的关系,我们将上面的代码完善一下,引入C语言函数的语法↓

为了直观,概念讲解直接在注释中给出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 为了调用printf()这个函数需要引入stdio.h头文件
#include <stdio.h>

// 下面的10~19行是一个完整的函数f
// 第一个int为函数的返回值,它指定了函数中return语句最终返回的值的类型
// 返回值后面紧跟函数名,他必须是一个合法的C语言标识符
// 函数名后面的一个圆括号,里面有若干变量的声明,用逗号分隔,这些变量叫做函数形参(形式参数),亦即
// 数学函数的自变量
// 形参声明同样需要给定类型,(int x)代表这个函数需要一个整型的参数,命名为x
// 形参列表-也就是(int x),之后紧跟一个花括号{},内有若干语句(实际上是一个复合语句),代表函数的实际运算
int f(int x){
// 和数学函数不同,数学上仅仅是一个对应关系f,指定了计算;
// 而C函数中可以声明中间变量来辅助计算,这里的y就是一个中间变量,实际上,它用来存储最终计算的结果
int y;

// 这里是最关键的对应关系f的体现,计算x的平方,将结果赋值给y进行临时保存
y = x*x;

// return语句,顾名思义,用于'返回'一个值,这个值的类型必须和前面的函数返回值类型相同(或可以进行转换)
// 将y的值返回,也就是作为这个函数f的函数值返回,一旦执行了return语句,其所在的函数(也就是f())立即结束运行
return y;
}

// 显然,main()也是一个函数!只不过它十分特殊,后面进行讲解
int main(){
int x = 10,x2; // 同样,可以视为中间变量
x2 = f(x); // 这条语句调用了f()函数,将main中的x作为参数(实际参数)传递给f()
printf("answer = %d\n",x2); // 这条语句调用了printf()函数,将一个格式化字符串和x2最为参数(实际参数)传递给printf()
return 0; // 同样,立即结束main()函数的运行,0作为返回值.
// 只不过,main函数特殊,其一旦结束,代表着整个程序结束!
}

注释已经写的十分完善,读者在一步步阅读,也在一步步分析上面代码的写法.但是还有两个概念:

  1. 函数头

    int f(int x)这一部分实际上是一个函数签名,它告诉了我们(更重要的是告诉编译器)这个函数接受1int类型的参数,并最终返回一个(任何函数都仅且仅能返回一个值)int类型的返回值作为函数调用的结果.

  2. 函数体

    1
    2
    3
    4
    5
    {
    int y;
    y = x*x;
    return y;
    }

    紧跟着函数头的是一个复合语句,在这里称之为函数体,它相当于指定了这个函数的真正运算,其内的各条子语句依次按照逻辑执行,最终(可能)返回一个值.

进一步分析结构

我们可以看到,一个完整的函数定义(注意不是函数声明!!!)包括两部分:函数头和函数体.

并且函数头指定了这个函数的相关信息(函数参数的个数及其类型,函数的返回值类型),而且隐含的一点是,它唯一确定了这个函数!

函数体一旦给出,代表给出了这个函数的定义,这样这个函数就真正意义上的彻底给出!

函数头中的圆括号(),其中的各个声明,称为形式参数,各个参数使用逗号,隔开,并且严格规定顺序,例如:

1
double function(int a,char b);

这个函数接受两个参数,第一个参数为int类型,第二个为char类型,返回一个double类型的值.

注意事项

  1. 然而,C语言的函数并不完全等同于数学函数,因为C语言的函数不一定需要参数,甚至,它可能都不需要返回一个值!

    我们后面很快就能看到相关例子!—其实我们已经见到了,那就是main函数!它往往不需要参数!

  2. 一个函数一旦给出函数体,意味着这个函数实现了定义,在整个程序的任何其他位置,都不能够给出这个函数的第二个定义,即使两个定义一模一样也不行!

  3. 我们很快就会学习到,有无给出函数体的区别及意义,这涉及到声明定义的区别.

    并且,C语言中,同一个函数(一个函数名)只能有"一种"函数头—或者准确点:函数签名.


本部分讲解了C函数的基本框架语法,接下来会分部分详细讲解函数这一重要组成部分!

---WAHAHA



上一篇:C语言教程-11-字符串

下一篇:C语言教程-12_2-深入分析函数和面向过程初识