C语言基本教程 第6课:函数

先看一个简单的例子,


PS: 故意截的图,免得你们复制粘贴,手敲吧 :)

这个小程序的功能是输入两个整数,然后输出两个数的和.

改造一下 ==>


对比第一个,发现两者实现的功能完全一样:

但是在第二个例子里边,出现了 第2行和第12行,这种没见过的东西,不要怕.

现在开始分析第二个例子,之前的教程说了,每一个C程序都是从 main()开始执行的,这个当然也不例外,

那么第一个执行的语句是 第12行:  get_sum();

这个时候就会跳转到 第2行,开始执行.

其实很简单,如果不考虑形式上的差异,其实就是用 { } 把原来main() 函数体内的内容 copy 到了 get_sum() 中,然后顺序执行.

这个 从第2行到第9行的get_sum() 就是函数.


函数是一段可以重复使用的代码,用来独立地完成某个功能,它可以接收用户传递的数据,也可以不接收。

无参函数的定义

如果函数不接收用户传递的数据,那么定义时可以不带参数。如下所示:

返回值类型  函数名(){
    函数体
}

说明:
  • 返回值类型可以是C语言中的任意数据类型,例如 int、float、char, void 等。
  • 函数名是标识符的一种,命名规则和标识符相同。函数名后面的括号( )不能少。
  • 函数体是函数需要执行的代码。即使只有一个语句,也要由{ }包围。
  • 在函数体中使用return语句返回数据,如果函数的返回值类型为 void, 即函数的返回值为空,则没必要用 return语句 。
  • return是C语言中的一个关键字,只能用在函数中,用来返回处理结果。

有参函数的定义

如果函数需要接收用户传递的数据,那么定义时就要带参数。如下所示:

返回值类型  函数名(参数列表){
    函数体
}

用户数据通过“参数列表”传递给函数,供函数处理。

参数(Parameter)本质上也是变量,定义时要指明参数类型和参数名称。参数列表中可以定义一个或多个参数,多个参数之间用逗号,分隔。参数列表中给出的参数可以在函数体中使用。

函数定义时给出的参数称为形式参数,简称形参;函数调用时给出的参数(传递的数据)称为实际参数,简称实参。函数调用时,将实参的值传递给形参,相当于一次赋值操作。注意:实参和形参的类型、数目必须一致。

return 语句可以有多个,可以在函数体的任意位置。但是函数一旦遇到 return 语句就返回(停止执行),后面的所有语句都不会被执行到.

接下来我们再写一个上述功能的有参数函数的例子:


在这个例子里, int get_sum(int x, int y)

返回值为 int 型, 有两个int 型  形式参数 x 和 y,

sum 接收函数返回值.

==============================

以上介绍的是我们自己的 自定义函数,

另外还有 系统提供的库函数,比如 之前我们使用的 printf() 和 scanf(),

需要使用 #include<stdio.h> 包含这个头文件之后才能使用.

我们可以在cfree的安装目录如下路径找到 stdio.h 这个文件,:


下边是 stdio.h 中 printf() 函数.



看到这里,爱动脑经的同学可能发现了4个问题:

1. 我怎么没有看到 printf() 的{ }以及其中的内容呢?

2. 怎么是分号结尾的 ?上边的例子可不是分号结尾的啊

3. 怎么还有 .h 文件,之前不是一直告诉我是 .c 源文件吗?


接下来对这几个问题一一解答:

1. 我怎么没有看到 printf() 的{ }以及其中的内容呢?

============>这个源文件由编译器的开发者实现, 已经被编译成 .o 或者.a 文件,包含在编译器中, 路径在 D:\asoft\cfree\mingw\lib

     这个大家知道是怎么回事就行,不必深究了.

2. 怎么是分号结尾的 ?上边的例子可不是分号结尾的啊

   =================>

 函数中的定义 的位置 在被调用(使用)的位置之前,不用声明. 

所谓声明(Declaration),就是告诉编译器我要使用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上。

函数声明的格式非常简单,相当于去掉函数定义中的函数体再加上分号;,如下所示:

返回值类型  函数名( 类型 形参, 类型 形参… );

也可以不写形参,只写数据类型:

返回值类型  函数名( 类型, 类型…);

函数声明给出了函数名、返回值类型、参数列表(参数类型)等与该函数有关的信息,称为 函数原型( Function Prototype

函数原型的作用是告诉编译器与该函数有关的信息,让编译器知道函数的存在,以及存在的形式,即使函数暂时没有定义,编译器也知道如何使用它。

有了函数声明,函数定义就可以出现在任何地方了,甚至是其他文件、静态链接库、动态链接库等。

如下:


函数中的定义 的位置 在被调用(使用)的位置之后,必须把函数声明 放在被调用(使用)的位置之前. 如下:


3. 怎么还有 .h 文件,之前不是一直告诉我是 .c 源文件吗?

============> 

头文件是方便了程序的文件组织的一个辅助文件,使文档可以模块化,它一般包含了一些 宏定义、自定义类型、函数原型等,这些函数在其他文件中使用时,include头文件就可以了.

通常头文件的组织和内容如下:


看一下hello.c 的变化:


test.c  如下:

test.h 如下:


重点介绍:

(1) 头文件是不编译的,因为C语言编译过程之前有个预编译过程。

在这个过程中用头文件中的内容替换源文件中“#include”命令,所以在编译器看来,没有头文件,只有源文件。

预编译过程还包括条件编译

      头文件为了防止被重复包含,通常的格式是:
      #ifndef __TEST__  // TEST 是头文件 test.h 名字的大写 前后使用 两个下划线
      #define __TEST__
      // your code
      #endif

(2) 如果是 系统头文件,使用 #include<> 尖括号, 如果是自定义 头文件,使用 #include" " 双引号.

     如下: 

#include<stdio.h>
#include"test.h"

函数的参数

在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为 形式参数 ,简称 形参

函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为 实际参数 ,简称 实参

形参和实参的功能是作数据传送,发生函数调用时,实参的值会传送给形参。

形参和实参有以下几个特点:
1) 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。

2) 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。

3) 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。

函数调用中发生的数据传送是单向的,只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。

函数调用过程中的参数传递本质是 用实参来初始化 形参, 而不是 实参替换形参.

函数的返回值

函数的返回值是指函数被调用之后,执行函数体中的程序段所取得的值,可以通过 return 语句返回。

函数中可以有多个 return 语句,但每次调用只能有一个return 语句被执行,所以只有一个返回值。

一旦遇到 return 语句,不管后面有没有代码,函数立即运行结束,将值返回,

为了使程序有良好的可读性并减少出错, 凡不要求返回值的函数都应定义为 void 类型


C语言不但提供了丰富的库函数,还允许用户定义自己的函数。每个函数都是一个可以重复使用的模块,通过模块间的相互调用,有条不紊地实现复杂的功能。可以说C程序的全部工作都是由各式各样的函数完成的,所以也把C语言称为函数式语言。

标准C语言(ANSI C)共定义了15 个头文件,称为“C标准库”,所有的编译器都必须支持,如何正确并熟练的使用这些标准库,可以反映出一个程序员的水平。

  • 合格程序员:<stdio.h>、<ctype.h>、<stdlib.h>、<string.h>
  • 熟练程序员:<assert.h>、<limits.h>、<stddef.h>、<time.h>
  • 优秀程序员:<float.h>、<math.h>、<error.h>、<locale.h>、<setjmp.h>、<signal.h>、<stdarg.h>

以上各类函数不仅数量众多,而且有的还需要硬件知识才能使用,初学者要想全部掌握得需要一个较长的学习过程。我的建议是先掌握一些最基本、最常用的函数,在实践过程中再逐步深入。由于课时关系,本教程只介绍了很少一部分库函数,其余部分读者可根据需要查阅C语言函数手册,网址是  http://www.cplusplus.com

还应该指出的是,C语言中所有的函数定义,包括主函数 main() 在内,都是平行的。也就是说,在一个函数的函数体内,不能再定义另一个函数,即不能嵌套定义。但是函数之间允许相互调用,也允许嵌套调用。习惯上把调用者称为主调函数,被调用者称为被调函数。函数还可以自己调用自己,称为递归调用。

main() 函数是主函数,它可以调用其它函数,而不允许被其它函数调用。因此,C程序的执行总是从 main() 函数开始,完成对其它函数的调用后再返回到 main() 函数,最后由 main() 函数结束整个程序。

==============================================================

目前我们接触到 的函数传递参数和返回值,都是 传递的变量的值, 由于指针还没有开始学习,所以更深层的传地址调用没办法讲解,

会在指针的课程上进行讲解.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值