目录
前言
终于来到函数部分了,首先还是说一下这篇文章的内容。主要内容讲函数的定义,函数调用,函数原型,函数的参数传递与返回值,递归函数和函数的递归调用,函数封装,函数复用,函数设计的基本原则,程序的健壮性,变量的作用域与存储类型,全局变量,自动变量,静态变量,寄存器变量,模块化程序设计方法。
从这篇文章开始,后面难道会越来越高,我尽量通俗的说明白,希望大家可以多多支持我,耐心的看完噢
一.函数
1.函数是C语言中模块化程序设计的最小单位。一个C程序可以由一个或多个源程序文件组成,一个源程序文件又可以由一个或多个函数组成。
2函数的分类:
标准库函数和自定义函数
3.函数的定义
函数在使用之前必须先定义,基本格式为:
返回值类型 函数名 (类型 形式参数1,类型 形式参数2,…)<-- 函数头部
{
声明语句序列
可执行语句序列
}
函数名是函数的唯一标识,用于说明函数的功能。不建议使用汉语拼英,通常变量名用小写字母开头,函数用大写字母开头。例如:Fact(int n)
函数体必须用一对花括号包围。在函数体内部定义的变量只能在函数体内访问,称为内部变量,函数头部参数表里的变量,称为形式参数,简称形参。若函数没有函数返回值,则需要用void定义返回值的类型。
例题:用函数编写计算整数n的阶乘。
代码如下:
long Fact(int n)
{
int i;
long result = 1;
for (i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
当然这个代码是不能运行的!
我们必须要被main()直接或者间接调用才能发挥作用,也就是函数调用。
二.向函数传递值和从函数返回值
1.函数调用
main()函数调用函数Fact()必须提供一个实际参数(实参)的表达式给被调用的函数,主调函数把实参的值复制给形参的过程叫参数传递。
例题:编写main函数,调用Fact()来计算m!,其中m的值从键盘输入。
代码如下:
#include<stdio.h>
int main()
{
int m;
int ret;
printf("Input m:");
scanf("%d", &m);
ret = Fact(m);
printf("%d!=%ld\n", m, ret);
return 0;
}
当然这个代码也是不能运行的!
把俩个代码合一起就可以用了!!!即下面代码
#include<stdio.h>
long Fact(int n)
{
int i;
long result = 1;
for (i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
int main()
{
int m;
int ret;
printf("Input m:");
scanf("%d", &m);
ret = Fact(m);
printf("%d!=%ld\n", m, ret);
return 0;
}
还有一种写法是:
#include<stdio.h>
long Fact(int n); //函数原型声明
int main()
{
int m;
int ret;
printf("Input m:");
scanf("%d", &m);
ret = Fact(m);
printf("%d!=%ld\n", m, ret);
return 0;
}
long Fact(int n) //函数定义
{
int i;
long result = 1;
for (i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
这俩种代码在功能上完全等价,形式上第一个程序里的函数Fact()的定义在main()之前,而第二个程序里函数Fact()的定义在main()之后,程序中第二行多了一句被称为函数原型声明的语句。
函数原型声明的语法格式通常与函数定义的头部是一致的,唯一区别是函数原型的末尾多了一个分号
三.函数封装与防御性程序设计
函数封装就是:当用户使用了ANSIC的标准库函数时,可以通过查找联机帮助或使用手册了解其用法,除了功能以外,用户最关心的时它对外的接口的含义,至于它的内部定义了哪些变量,使用了什么算法等细节内容,全被封装起来,用户看不到,也不必去关心,这就是函数封装。
在上面程序中输入:-10 会显示为-10!=1,显然是不对的。
下面对上述代码改进:
#include<stdio.h>
long Fact(int n); //函数原型声明
int main(void)
{
int m;
int ret;
printf("Input m:");
scanf("%d", &m);
ret = Fact(m);
if (ret == -1)
{
printf("Input data error!\n");
}
else
{
printf("%d!=%ld\n", m, ret);
return 0;
}
}
long Fact(int n) //函数定义
{
int i;
long result = 1;
if (n < 0)
{
return -1;
}
else
{
for (i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
}
俩次输入的结果如下:
四.函数设计的基本原则
一般来说,设计函数时,需要遵循以下几项基本原则
1.函数的规模要小,尽量控制在50行代码以内
2.函数的功能要单一
3.每个函数只有一个入口和一个出口
4.清楚地定义函数的行为
5.在函数的入口处,对参数的有效性进行检查
6.执行某些敏感操作之前,应该检查操作数及其类型的合法性
7.不能认为调用一个函数总会成功
8.当函数需要返回值时,应确保函数中的所有控制分支都有返回值,函数没有返回值应该用void声明。