C语言系列(22)——函数(01)
一、什么是函数
函数是一组一起执行一个任务的语句
每个 C 程序都至少有一个函数,即主函数 main()
,所有简单的程序都可以定义其他额外的函数。
将程序中的实现重复功能的代码,整合成一个函数,这样可以减少重复冗余代码、提高开发效率、便于维护。
二、函数定义和使用
1. 定义语法
返回值类型 函数名(参数1,参数2,...)
{
//函数体,实现功能的代码
return 返回值;//类型需与返回值类型一致
}
- 返回类型:一个函数可以返回一个值。有些函数执行所需的操作而不返回值,在这种情况下,是关键字 void。
- 函数名:这是函数的实际名称。符合C语言标识符定义规则。
- 参数:参数就像是占位符。当函数被
调用时
,您向参数传递一个值,这个值被称为实际参数
。参数列表包括函数参数的类型
、顺序
、数量
。参数是可选的,也就是说,函数可能不包含参数。- 形参:函数
定义
时的参数
。(上述定义中的,参数1,参数2为形参) - 实参:
调用
函数是传递的参数
。
- 形参:函数
- 函数体:函数主体包含一组定义函数执行任务的语句。
2. 函数分类
根据返回值和参数列表,函数可以分为:
- 无参数无返回:函数定义时,
没有形参
列表,返回值类型为void
。 - 无参数有返回:函数定义时,
没有形参
列表,有返回值类型(基础类型,结构体、指针等)。 - 有参数无返回:函数定义时,
有形参
列表,返回值类型为void
。 - 有参数有返回:函数定义时,
有形参
列表,有返回值类型。
3. 使用函数
无参数无返回:
void 函数名()
{
//函数体,实现功能的代码
return;//无需返回值
}
- 例:定义一个函数,打印10句“I Love you”。
void printLove()
{
int i = 0;
while (i < 10)
{
printf("I love you\n");
i++;
}
return;
}
- 调用函数:在其他函数中调用,如在main中:
int main()
{
//函数调用,使得main函数更简洁,而printLove()易可在其他函数中调用,实现功能复用
printLove();
return 0;
}
打印10句I Love you
无参数有返回:
数据类型 函数名()
{
//函数体,实现功能的代码
return 值;
}
- 例:定义一个函数,返回两个整数的和
int sum() // 返回值类型为int
{
int a = 20;
int b = 10;
return a + b; // 返回值
}
- 调用:在其他函数中调用,如在main中:
int main()
{
int a = sum();//有返回值,就用一个同类数据类型的变量接受返回的值
printf("%d\n", a);
return 0;
}
打印:30
有参数无返回:
void 函数名(参数1,参数2,...)
{
//函数体,实现功能的代码
return;
}
- 例:定义一个函数,打印1~n之间的数,n由参数传入
void printNumber(int n)//形参,定义时参数列表中的参数为形式参数,实际值由调用者传入
{
int i = 1;
for ( i = 1; i < n; i++)
{
printf("%d ", i);
}
}
- 调用:在其他函数中调用,如在main中:
int main()
{
printNumber(10);//实参,调用者传入的为实际参数
return 0;
}
有参数有返回:
返回值类型 函数名(参数1,参数2,...)
{
//函数体,实现功能的代码
return 值;
}
- 例:定义一个函数,对两个数进行除法运算后,返回其值
float divider(float a, float b)//形参,定义时参数列表中的参数为形式参数
{
return b == 0 ? b : a / b;// 返回0或两个值相除的结果
}
- 调用:在其他函数中调用,如在main中:
int main()
{
printf("%f\n", divider(10, 20));//实参,调用者传入的为实际参数
return 0;
}
4. 函数声明
函数声明,将暴露给其他文件或函数,使其可以被调用
float divider(float a, float b);//函数声明,暴露给main函数,时期能调用
int main()
{
float f = divider(10, 20);//函数调用
printf("%f\n", f);
system("pause");
return 0;
}
// 函数定义在其他文件,或在调用者(如main函数)的下方,则需要在调用者之前(文件上方)声明
float divider(float a, float b)//函数定义
{
return b == 0 ? b : a / b;
}
三、作用域和生命周期
作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问。
C语言中有三个地方可以定义变量:
在函数或块内部的局部变量
在所有函数外部的全局变量
在形式参数的函数参数定义中
例:注意看代码中的注释
int g = 0;//2、全局变量定义及初始化,在所有函数的外部定义
void printNumber(int a, int b);
int main()
{
//1、局部变量,在函数main内部定义,只能再main函数内部被使用
int a = 10, b = 20;
g = a + b;//全局变量可以在(其声明可见的)任何函数中使用。
printf("main: a = %d, b = %d, g = %d\n", a, b, g);
printNumber(a, b);
system("pause");
return 0;
}
void printNumber(int a, int b)
{
//(int a, int b)函数调用时,参数传递的隐含代码为 :
//int a = 10;//(实参a的值赋值给形参a)
//int b = 20;//(实参b的值赋值给形参)
//int a;//不能再定义a变量,因为形参已经定义
printf("printNumber1: a = %d, b = %d\n", a, b);//打印main函数实参传递过来的值
//改变形参a和b的值
a = 11;
b = 22;//a,b也是局部变量,可以在该函数内部被使用
printf("printNumber2: a = %d, b = %d\n", a, b);//打印改变后形参变量的值
printf("printNumber3: g = %d\n", g);//可以直接使用全局变量
}
打印:
main: a = 10, b = 20, g = 30
printNumber1: a = 10, b = 20
printNumber2: a = 11, b = 22
printNumber3: g = 30
全局变量,从定义到程序结束,一直可用。存放在静态区(全局区)
局部栈变量,随着函数或块结束
而销毁(回收)
。
局部堆变量,手动销毁(回收)
。