C语言函数入门

由于采用了函数模块式的结构,C语言易于实现结构化程序设计。使程序的层次结构清晰,便于程序的编写、阅读、调试。

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

C 语言大致有下面这些种类的函数:

  1. 字符类型分类函数:用于对字符按ASCII码分类:字母,数字,控制字符,分隔符,大小写字母等。
  2. 转换函数:用于字符或字符串的转换;在字符量和各类数字量(整型,实型等)之间进行转换;在大、小写之间进行转换。
  3. 目录路径函数:用于文件目录和路径操作。
  4. 诊断函数:用于内部错误检测。
  5. 图形函数:用于屏幕管理和各种图形功能。
  6. 输入输出函数:用于完成输入输出功能。
  7. 接口函数:用于与DOS,BIOS和硬件的接口。
  8. 字符串函数:用于字符串操作和处理。
  9. 内存管理函数:用于内存管理。
  10. 数学函数:用于数学函数计算。
  11. 日期和时间函数:用于日期,时间转换操作。
  12. 进程控制函数:用于进程管理和控制。
  13. 其它函数:用于其它各种功能。

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

 

形式参数和实际参数

实参出现在主调函数中,进入被调函数后,实参变量也不能使用。形参和实参的功能是作数据传送。发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。

函数的形参和实参具有以下特点:

  • 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。
  • 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。
  • 实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。


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

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

当被调函数的函数定义出现在主调函数之前时,在主调函数中也可以不对被调函数再作说明而直接调用,反之则会报错,

在主调函数中调用某函数之前应对该被调函数进行说明(声明),这与使用变量之前要先进行变量说明是一样的。在主调函数中对被调函数作说明的目的是使编译系统知道被调函数返回值的类型,以便在主调函数中按此种类型对返回值作相应的处理。

 

取消注释皆可。

对库函数的调用不需要再作说明,但必须把该函数的头文件用include命令包含在源文件前部。

 数组用作函数参数有两种形式,一种是把数组元素(下标变量)作为实参使用;另一种是把数组名作为函数的形参和实参使用。

数组名作为函数参数

用数组名作函数参数与用数组元素作实参有几点不同。

1) 用数组元素作实参时,只要数组类型和函数的形参变量的类型一致,那么作为下标变量的数组元素的类型也和函数形参变量的类型是一致的。因此,并不要求函数的形参也是下标变量。换句话说,对数组元素的处理是按普通变量对待的。用数组名作函数参数时,则要求形参和相对应的实参都必须是类型相同的数组,都必须有明确的数组说明。当形参和实参二者不一致时,即会发生错误。

2) 在普通变量或下标变量作函数参数时,形参变量和实参变量是由编译系统分配的两个不同的内存单元。在函数调用时发生的值传送是把实参变量的值赋予形参变量。 在用数组名作函数参数时,不是进行值的传送,即不是把实参数组的每一个元素的值都赋予形参数组的各个元素。因为实际上形参数组并不存在,编译系统不为形参 数组分配内存。那么,数据的传送是如何实现的呢?在我们曾介绍过,数组名就是数组的首地址。因此在数组名作函数参数时所进行的传送只是地址的传送,也就是 说把实参数组的首地址赋予形参数组名。形参数组名取得该首地址之后,也就等于有了实在的数组。实际上是形参数组和实参数组为同一数组,共同拥有一段内存空 间。


上图说明了这种情形。图中设a为实参数组,类型为整型。a占有以2000为首地址的一块内存区。b为形参数组名。当发生函数调用时,进行地址传送,把实参 数组a的首地址传送给形参数组名b,于是b也取得该地址2000。于是a,b两数组共同占有以2000为首地址的一段连续内存单元。从图中还可以看出a和 b下标相同的元素实际上也占相同的两个内存单元(整型数组每个元素占二字节)。例如a[0]和b[0]都占用2000和2001单元,当然a[0]等于 b[0]。类推则有a[i]等于b[i]。

 

 1 #include<stdio.h>
 2 void changeInt(int a){
 3     a = 0;
 4 }
 5 void changeArray(int a[2]){
 6     int i;
 7     for(i=0; i<3; i++){
 8         a[i] = 24;
 9     }
10 }
11 int main()
12 {
13     int m = 9, i;
14     int array[3] = {1,2,3};
15     changeInt(m);
16     changeArray(array);
17     printf("一般类型:%d\n", m);
18     printf("数组类型:");
19     for(i=0; i<3; i++){
20             printf("%d", array[i]);
21         }
22     return 0;
23 }

 

 

3) 前面已经讨论过,在变量作函数参数时,所进行的值传送是单向的。即只能从实参传向形参,不能从形参传回实参。形参的初值和实参相同,而形参的值发生改变 后,实参并不变化,两者的终值是不同的。而当用数组名作函数参数时,情况则不同。由于实际上形参和实参为同一数组,因此当形参数组发生变化时,实参数组也 随之变化。当然这种情况不能理解为发生了“双向”的值传递。但从实际情况来看,调用函数之后实参数组的值将由于形参数组值的变化而变化。

用数组名作为函数参数时还应注意以下几点:
①形参数组和实参数组的类型必须一致,否则将引起错误。

②形参数组和实参数组的长度可以不相同,因为在调用时,只传送首地址而不检查形参数组的长度。当形参数组的长度与实参数组不一致时,虽不至于出现语法错误(编译能通过),但程序执行结果将与实际不符,这是应予以注意的。

C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。

关于局部变量的作用域说明以下几点:

  • 主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。因为主函数也是一个函数,它与其它函数是平行关系。这一点是与其它语言不同的,应予以注意。
  • 形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。
  • 允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。如在前例中,形参和实参的变量名都为n,是完全允许的。
  • 在复合语句中也可定义变量,其作用域只在复合语句范围内。

 

posted on 2015-05-13 22:32  liujie037  阅读(418)  评论(0编辑  收藏  举报

导航