目录
12.1 函数概述
12.1.1 函数的概念及作用
- 函数化结构是C语言程序的重要特征
- 使用函数,能提高程序设计效率
- 缩短程序代码,使程序简练紧凑
12.1.2 函数的分类
- 标准库函数
- 用户自定义函数
12.1.3 函数举例
求a!+b!+c!的值。程序如下:
- 程序结构只有main()函数的阶乘程序
程序缺点:求阶乘程序段重复三遍,结构不紧凑
void main( )
{
int a,b,c,i;
long t,sum;
printf("input a,b,c:");
scanf("%d,%d,%d",&a,&b,&c);
for(t=1,i=1;i<=a;i++)
t=t*i;
sum=t;
for(t=1,i=1;i<=b;i++)
t=t*i;
sum+=t;
for(t=1,i=1;i<=c;i++)
t=t*i;
sum+=t;
printf("SUM=%ld\n",sum);
}
- 使用用户函数的阶乘程序
引入求阶乘函数rfact(),将程序优化为:
long rfact(int n)
{
long t;
int i;
for(t=1,i=1;i<=n;i++)
t*=i;
return(t);
}
void main()
{
long rfact(int n);
int a,b,c,i;
printf("input a,b,c:");
scanf("%d,%d,%d",&a,&b,&c);
printf("SUM=%ld\n",
rfact(a)+rfact(b)+rfact(c));
}
12.2 函数的定义
12.2.1 函数定义的一般形式
函数定义是指在程序中编写具有特定功能的用户函数。函数定义的一般格式如下:
函数类型 函数名(形式参数表)
{
函数体
}
12.2.2 函数定义的说明
- 函数名是对函数的标识,是符合标识符命名规则的任何合法标识符。
- 形式参数表是用逗号分隔的一组变量说明,其格式为:数据类型1 形参1,数据类型2 形参2,……,数据类型n 形参n
- 函数体是实现函数功能的全部语句。
- 函数类型:当函数有具体返回值时,为函数值的数据类型;当函数没有具体的返回值时,函数类型为void型。
- 当函数不需要参数时,形参变量表用void填充。有的C语言系统,在定义无参数函数时允许形参表为空,但函数名后面的括号()不能省略。
12.2.3 函数定义举例
输出两个实数中的最大数。程序如下:
//定义1
float rmax2(float x,float y)
{
float m;
m=x>y?x:y;
return(m);
}
//定义2
float rmax2(float x,float y)
{
if(x>y)
return(x);
else
return(y);
}
//定义3
float rmax2(float x,float y)
{
return(x>y?x:y);
}
求和函数sum(),计算1+2+3+…+n-1+n的值。程序如下:
int sum(int n)
{
int s,i;
for(s=0,i=1;i<=n;i++)
s+=i;
return(s);
}
12.3 函数的调用
12.3.1 函数原型和函数声明
- 函数原型
函数原型就是对已经定义的函数的概要描述,是定义函数时函数体以外的那些内容。一般形式如下:
函数类型 函数名(数据类型1 形参1,数据类型2 形参2,…,数据类型n 形参n);
函数原型中对形参表进行描述时,允许省略所有形参的名称,只保留各个形参的类型说明,但它们个数和顺序完全一致。函数原型的简化形式如下:
函数类型 函数名(数据类型1, 数据类型2, … , 数据类型n)
- 函数声明
在进行函数调用之前,需对被调用函数进行函数声明。函数声明有多方面的作用,其中之一是编译程序利用函数声明对函数调用的合法性进行检查,凡是与函数原型不匹配的函数调用一律视为非法调用。
函数声明可以在主调函数中进行,也可以在程序开始集中进行(也就是在函数外声明,声明语句与main函数同级)。若采用后一种形式,则在主调函数中对被调用函数的声明即可省略。
12.3.2 函数调用的一般形式
函数调用是指对已定义函数的具体应用。函数调用的一般形式如下:
函数名(实参表)
发生函数调用时,函数中的形参将得到实参表中的数据,然后执行函数体语句,实现函数功能。
进行函数调用时,需注意以下事项:
- 函数调用的实参个数必须与形参个数相同。
- 实参与形参按照在参数表中的位置一一对应传值,实参与形参的名称是否相同对调用传值无任何影响。
- 实参与形参对应位置上的数据类型应该一致。
- 对于无参数函数,即形参表为void的函数,函数调用时实参表必须为空,不能有任何内容。
12.3.3 函数调用的三种情况
(1)函数调用以语句的方式出现,通常只完成一种操作,不带回返回值。例如,调用例9-4的p_star()函数,输出20个连续“*”字符:
void p_star(int n)
{
int i;
for(i=1;i<=n;i++)
printf("%c",'*');
}
void main()
{
void p_star(int); /* 函数声明*/
p_star(20); /* 函数调用*/
}
(2)函数调用出现在表达式中,是表达式的一部分。例如,调用例9-3定义的求和函数sum(),计算如下表达式的值:
程序代码如下:
int sum(int n)
{
int s,i;
for(s=0,i=1;i<=n;i++)
s+=i;
return(s);
}
void main()
{
int sum(int); /* 声明sum()函数 */
int s;
s=sum(20)+sum(50); /* 两次调用sum()函数 */
printf("SUM=%d\n",s);
}
(3)函数调用作为一个函数的实参。例如,调用例9-2定义的求两个实数的最大数rmax2(),求三个数的最大数:
float rmax2(float x,float y)
{
return(x>y?x:y);
}
void main()
{
float rmax2(float,float); /* 声明rmax2()函数 */
float a,b,c,max;
scanf("%f,%f,%f",&a,&b,&c);
max=rmax2(rmax2(a,b),c);
printf("Max=%f\n",max);
}
12.4 函数值和return命令
函数值是函数执行后带回的一个结果,通常称为函数的返回值。
用户函数的返回值通过函数体中的return命令获得。其一般格式如下:
return 表达式
return命令将“表达式”的值作为函数的返回值,同时结束函数运行,返回到调用它的上层函数位置。
关于return命令的说明如下:
(1)return命令也可以使用如下格式:
return (表达式)
(2)在一个函数中允许有多个return命令,执行到任何一个return命令都将返回到主调函数。
(3)当函数不需要具体的返回值时,函数体中的return命令不使用参数。(实际上,当return命令省略参数时,return语句也就可有可无了。缺少return语句的函数,执行完最后一个语句后自动返回)
12.5 变量的作用域与存储类型
12.5.1 变量的作用域
- 局部变量
局部变量也称内部变量,其相关说明如下:
(1)在函数体内定义;
(2)只能在定义它的函数中使用;
(3)在一个程序的不同函数中可以定义同名的变量;
(4)函数的形参变量和在函数体内定义的变量都是局部变量;
(5)函数执行结束后形参变量立即消失;
(6)在函数体内定义的局部变量是否随函数结束而消失,要取决于变量的存储类型。
局部变量示例程序如下:
#include <stdio.h>
void prn_1(int); /* 函数声明 */
void prn_2(); /* 函数声明 */
void main()
{
int i; /* 定义局部变量i ,它仅在main()函数内有效 */
for(i=0;i<10;i+=5)
{
prn_1(i); /* 用变量i作实参进行函数调用 */
prn_2();
}
}
void prn_1(int n) /* 输出整数值的函数 */
{
int i; /* 定义局部变量i,它仅在prn_1()函数内有效 */
for(i=1;i<=5;i++)
printf("%5d",n+i);
printf("\n");
return;
}
void prn_2() /* 输出一条横线的函数 */
{
int i; /* 定义局部变量i,它仅在prn_2()函数内有效*/
for(i=1;i<30;i++)
printf("%c",'-');
printf("\n");
return;
}
- 全局变量
全局变量的相关说明如下:
(1)在程序的任何一个函数体外定义。
(2)在一个程序中,凡是在全局变量之后定义的函数,都可以使用在其之前定义的全局变量。
(3)一个全局变量,可以被多个函数使用, 但并不一定能被所在程序中的每一个函数使用。
(4)全局变量也有一定的作用范围。
全局变量示例程序如下:
int a=3,b=5; /* 定义全局变量 */
max(int a,int b)
{
return(a>b?a:b); /* a、b是形参 */
}
void main()
{
int a=8; /* 定义局部变量 */
printf("MAX=%d\n",max(a,b)); /* a是局部变量,b是全局变量 */
}
12.5.2 变量的存储类型
数据类型和存储类型是C语言中变量的两种不同属性,数据类型规定了变量能存储哪一类数据,存储类型则规定了变量在计算机中怎样存储。C语言变量的存储类型有3种,即auto型、static型和register型。现介绍最常用的两种。
- auto型变量
auto型变量通常称为自动变量。
只有函数的局部变量才能定义为auto型。
auto型变量在函数被调用时为其分配存储空间,存储于内存的动态存储区,函数执行结束时存储空间自动释放。即:auto型变量随函数的调用而产生,随函数的执行结束而消失。
每次进行函数调用时,相关的auto型变量都被初始化。
auto型变量的定义形式为:auto 数据类型 变量;
在定义局部变量时,如果缺省存储类型项,则系统默认为存储类型是auto型。
- static型变量
static型变量通常称为静态变量,它存放在内存的静态存储区,在编译时分配存储空间,并进行初始化。
对于没有赋初值的static型变量,编译系统会自动为数值型的变量赋0值,为字符型的变量赋空值‘\0’。
静态变量定义的形式为: static 类型标识符 变量名;
在函数内定义的静态变量称为静态局部变量,在函数外定义的静态变量成为静态全局变量。
static型局部变量并不因函数运行结束而消失,而是始终存在,当再次进入该函数时, 将保留上次的结果。但无论在什么情况下,都不能被其他函数使用。