C语言函数:从“为什么函数是程序的基本组成单位呢”讲起?

前言:为什么函数是程序的基本组成单位呢?


函数通常具有一定的功能,并且它的功能是通过把使用者提供的输入变成输出体现的。程序也具有功能,它的功能也是通过把使用者的输入变成输出体现的,函数与程序的区别在于它们的使用者不同。函数常被其他函数调用,而程序通常由人使用。

在规模上,程序的功能强大,而函数的功能单一。程序中main函数的作用主要是获得用户的输入并把最终的处理结果反馈给用户,而数据处理的任务多通过调用其他函数来完成。函数的封闭性使得编程人员在实现函数时不必考虑外界的影响。

当程序由多个函数组成后,在某个函数中心定义的变量将属于这个函数而不能在程序的其他地方使用,即变量的使用范围受其作用域的限制。变量的作用域与变量的生命周期有关。全局变量的生命周期贯穿整个程序运行期间,所以,它的作用域可以扩展到程序的任何地方。虽然全局变量为函数间共享数据提供了便利,但使用全局变量时必须时刻特别小心,全局变量不仅能影响函数的封闭性,还会降低程序的可读性。

递归函数是函数解决“特定问题”的一种有效手段。如果在分析问题时发现原问题可以转化为“性质相同,规模较小” 的子问题,则此类问题大多可以用递归算法解决。递归不仅是一种解决问题的思路,更是一种独特的重复。

函数重用是代码重用最基本的形式,代码重用可以提高编程效率和程序的健壮性。


一.函数的定义:


1.定义函数常用的形式为:


返回值类型 函数名(参数列表)
{
代码段
}

返回值类型为函数值的类型,不能为数组。函数名是一个标志符。参数列表规定了函数输入值得个数和类型。

参数列表的参数又称为形式参数,简称形参。
函数的输出值即函数值由return语句返回给函数的使用者(主调函数)。
return语句的形式有两种:
return
return 表达式

提示:
表达式两边可以加小括号,故又可以写成return(表达式);

例题:定义一个判断正整数是否为质数的函数。

#include<math.h>
int isPrime(int n)
{
int r,i;
if(n==1)
  return 0;
r=(int)sqrt(n);
for(i=2;i<=r;r++)
  if(n%i==0)
    break;
return (i==r+1);
}

二.函数调用与函数声明


1.函数调用分析:


使用函数时需要调用函数。发生函数调用时,主调函数会保存执行状态,中断执行,被调函数执行完,主调函数先恢复原来的执行状态,然后从中断处开始继续执行。

函数调用的形式为:

函数名 (实际参数表)

其中,函数名为被调用函数的名字,实际参数表由与形参数目相同的表达式组成。实参是实际参数的简称。实参之间也用逗号隔开。

#include命令的作用是把指定文件的内容插入到该语句所在位置并取代该语句,从而把指定的文件内容合并到当前的源程序文件中。#include命令的常见形式为:

#include<文件名>或#include"文件名"

其中<>和”“用于指定文件名所在的目录。<>表示到编译系统指定的目录下查找欲包含的文件。

“”表示先到当前目录中查找欲包含的文件,找不到时再到指定的目录下查找。所谓“当前目录”是指包含#include命令的源文件所在的目录。

指定目录中的文件多为库文件。而程序员自定义的文件多放在“当前目录”中。

2.函数声明的作用:


当一个函数在定义之前被调用,编译系统会在函数调用处停止编译并报错,即使该函数就在下面相邻的代码中。函数声明可以使编译器“忽略”函数还没有定义这个错误,继续编译代码。

函数声明的一般形式为函数首部加上分号,即:
返回值类型 函数名(参数列表)

函数声明可以使得编译器可以在没有函数定义的情况下检查函数的合法性,如实参的个数是否与形参一样,类型是否与形参兼容。

3.使用参数类型为一维数组的函数


数组元素就是普通变量,因此,数组元素作为参数时没有任何特别之处。数组类型也可以作为形参。

函数定义中数组形参的长度可有可无,但方括号不能省略。函数中的形参的类型应理解为一维整型数组,而不能理解为长度为定值的一维整型数组,只要是一维整形数组,无论长度都可以作为实参。

形参的类型是数组时,在函数体中改变形参数组元素的值,实际上就是改变实参数组中同一下标的数组元素的值。

4.变量作用域


每个变量都有自己的作用域。变量的作用域是指程序中变量起作用的区域。只有在作用域内,变量才能正常使用。常见的变量作用域有两类:复合语句作用域和文件作用域。

如果变量在复合语句中定义,则该变量的作用域为复合语句作用域,从变量定义处起至复合语句结束处止。具有复合语句作用域的变量称为局部变量。函数体就是一个大的复合语句,因此函数体内定义的变量多为局部变量。另外,函数的形参也是局部变量,作用域覆盖整个函数体。显然,在一个函数中定义的变量不能用于其他函数中。

如果变量不在复合语句中定义,则该变量的作用域为文件作用域,从变量定义处起至文件结束处止。具有文件作用域的变量称为全局变量。

在作用域之外不能使用变量使得函数具有封闭性。一方面,可以在函数体内使用任意的变量名而不必担心因变量重名而影响其他函数;另一方面,仅限在函数体使用的局部变量也不可能受其他函数的影响。所谓函数的封闭性,是指用相同的实参多次调用函数式时,函数的返回值每次都相同。如果函数定义中只使用局部变量,则函数显然具有封闭性。

局部变量有时会和此前定义的变量重名,在新定义的局部变量的作用域中,可能会出现两个同名变量的作用域重叠的情况。C语言规定,多个作用域不同的同名变量在共同作用域内,后定义中的变量有效,也就是作用域最小的变量起作用。

5.文件作用域扩展


函数也有作用域,准确地说是函数名也有作用域。函数的作用域当然也是指可以使用函数的区域。

函数具有文件作用域,从函数开始定义处起至源文件结束止。虽然不能在函数作用域之外使用函数,但有了函数声明之后函数就可以先使用后定义。函数声明实际上用于扩展函数的作用域。具有文件作用域的全局变量可以像函数一样,扩展自己的作用域。

在前面加个关键字extern,全局变量定义语句就变成了全局变量声明语句。声明的作用只是扩展作用域,声明的函数和全局变量必须在程序的其他地方定义。声明后,全局变量的作用域将扩展为从声明语句开始。如果声明语句在一个函数体或复合语句中,全局变量作用域的扩展将在封闭花括号“}”处止;否则,将在源文件结束处止。

全局变量标识的存储单元在程序开始执行前已经分配,程序执行完毕才释放。在程序运行期间,与全局变量相关的存储单元一直属于变量所有,这是全局变量无论在何处定义都可以通过声明来扩展其作用域的根本原因。局部变量标识的存储单元只有在执行到变量的“定义语句”时才分配,变量定义语句所在的复合语句执行完毕后就自动释放。出了作用域之后,局部变量标识的存储单元已经不再属于局部变量所有,程序中自然也就不能再使用它。

6.使用关键字static限制文件作用域


为了防止全局变量的误用,可以用关键字static限制全局变量的作用域。在定义全局变量的时,类型前可以加一个关键字static,就可以将全局变量的作用域限制在当前源文件中,而不能被扩展到其他源文件中。

7.rand函数,srand函数和time函数
rand函数和srand函数在stdlib.h中声明。rand函数的功能是返回一个0到RANDMAX之间的随机数。RANDMAX为stdlib.h中定义的符号常量。在程序中,多次调用rand函数可以产生一系列的随机数,但是当再次执行程序时,rand函数将产生重复的随机序列。

srand函数的头部为void srand(unsigned int seed)。调用函数可以改变rand函数的种子,从而使rand函数可以产生不同的随机序列。由rand函数的算法可知,在多次调用函数rand函数产生随机序列之前,仅需要调用srand函数一次。

time函数在time.h中声明,它返回从公元1970.1.1.0时0分0秒起到现在所经过的秒数。它常用的调用的方式为time(NULL)。程序总是在不同时刻运行,因此,time(NULL)的返回值在每次程序运行时都不相同,把它作为rand函数的种子,就可以保证rand函数在每次程序运行时都能够产生不同的随机序列。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值