目录
一、为什么使用函数
如果我们需要编写的程序功能较多,把所有的程序代码都写在一个主函数(main函数)中,会使主函数变得冗长、庞杂,不利于后续的阅读和维护。
这时,就需要模块化编程,事先把一些常用的程序编写成函数(function,意思可以是“函数”,也可以是“功能”),需要使用的时候,直接调用即可。
而函数又分为两种:①库函数
②用户自己定义的函数
二、函数的定义
函数定义的四要素:
①函数的数据类型,即返回值的数据类型
②函数名称
③形参说明
④完成功能的函数体;
定义方法:
(1)定义无参函数
一般形式:
类型名 函数名()
{
函数体
}
或
类型名 函数名(void)
{
函数体
}
tips:void表示“空”,即函数没有参数
(2)定义有参函数
一般形式:
类型名 函数名(形式参数)
{
函数体
}
例子:写一个求x和y中最大数的函数
#include <stdio.h>
int main()
{
int max(int x, int y);//声明函数max
int a, b, c;
printf("Please input a & b:");//提示输入
scanf("%d%d", &a, &b);//输入两个实数
c = max(a,b);//调用max函数
printf("%d\n",c);
return 0;
}
int max(int x, int y)//定义函数max
{
int z;
z = x>y ? x : y;
return(z);
}
分析:求x和y中大者的函数单独写成一个模块,需要使用时,要在主函数要先声明函数(可以简单地把已定义的函数的首部照抄+分号“;”),再调用函数。在调用的过程中,把实参的值传递给被调用函数的形参。
tips:程序的执行都是从main函数开始的,无论用户自己定义的函数写在main函数的前面还是后面都是无所谓的。
三、函数的调用
实参与形参
实参:在主函数要调用一个函数,函数后面括号中的参数称为“实际参数”(简称“实参”)。
函数也可以作为另一个函数调用时的实参,如
c = max(d,max(a,b));
形参:在声明或者定义一个函数,函数后面括号中的参数称为形式参数”(简称“形参”)。
函数调用的一般形式:
函数名(实参表列)
当有多个实参时,用逗号“,”隔开。
四、拓展
使用库函数的时候,为什么要引用头文件?
因为在头文件中,有函数声明(前面也提到:要使用函数时,要事先声明函数,才能调用),当使用到多个头文件中的库函数时,直接引用头文件,即可方便快速解决。
五、函数的传参
变量如果只在函数体里面声明,只能被该函数使用,而其他函数是不能使用的。
如:a,b只会在main函数中使用,而max函数用不了。
解决办法:
①全局变量
全局变量就是在所有函数外说明的变量,全局变量一经定义后就会程序的任何地方看见。使用顺序不当,变量的值发生改变,可能会出错,建议少用。
②值传递方式
以上求x和y中最大数的函数就是用值传递方式。
注意:实参和形参在数量上、类型上、顺序上要严格一致,否则会发生“类型不匹配”的错误。
写一个交换两个数的函数,如
#include <stdio.h>
void swap(int x, int y);
int main()
{
int m = 10 , n = 20;
//printf("input m&n:");
//scanf("%d,%d", &m, &n);
printf("%d %d\n", m,n);
swap(m, n);//m,n是实参
printf("%d %d\n", m,n);
return 0;
}
/*交换两个数*/
void swap(int x, int y)//a,b是形参
{
int temp;
temp = x;
x = y;
y = temp;
}
运行结果:
从结果看出,两个数字根本没有发生交换,原因:m,n与x,y是不同的地址,只是形参m,n做了交换,而实参x,y没有交换,这就无法解决。(要解决这问题就需要用到地址传参)
所以,形参是在函数被调用时才分配的内存,调用结束就即刻释放内存单元。形参无法返回到main函数当中去。
③指针传递(地址传递)
按地址传递参数,实参为变量的地址,而形参为同类型的指针。
被调用函数中对形参的操作将直接改变实参的值。
#include <stdio.h>
void swap(int *x, int *y);
int main()
{
int m = 10 , n = 20;
//printf("input m&n:");
//scanf("%d,%d", &m, &n);
printf("%d %d\n", m,n);//打印交换前m,n的值
printf("%p %p\n",&m,&n);//打印交换前m,n的地址
swap(&m, &n);//m,n是实参
printf("%d %d\n",m, n);//打印交换后m,n的值
printf("%p %p\n",&m,&n);//打印交换后m,n的地址
return 0;
}
/*交换两个数*/
void swap(int *x, int *y)//a,b是形参,int x = m
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
执行过程如图:
④值传递与指针传递的区别
值传递是将实参传递给形参,而指针传递是将实参的地址传递给形参。
如果要改变实参的值,就需要用到指针传递,如果只是为了获取实参的值,值传递即可。
编程时,实现地址的传参,但不改变实参的方法:const *p。