6. 函数
把“释放技能”“计算伤害”封装成函数,在 main 里调用。本节对应考纲 6。
这一章在学什么
之前所有代码都写在 main 里。函数就是把一段功能单独写成一块,起个名字,在 main 里「调用」——就像游戏里按一个键就触发一个技能,函数就是那个“技能”,调用就是“按键”。
要学会:怎么定义函数(返回类型、函数名、参数、大括号里的代码)、怎么在 main 里调用(写函数名和实参)。如果调用写在定义前面,要在前面加函数声明(原型),否则可能编译报错。
本节考纲要点
- 掌握 函数的定义及调用
- 掌握 被调用函数的声明和函数原型
- 了解 函数的嵌套及递归调用
- 掌握 数组作为函数参数
- 了解 局部变量和全局变量
本节代码里的英文词
use_skill— 释放技能id— 编号(如技能编号)main— 主函数(程序入口)return— 返回(结束函数)hp— 血量(health 的缩写)void— 无返回值int— 整数类型
为什么用函数
函数能解决什么问题
把一段“会重复用”或“功能独立”的代码包成一个函数,需要时写一句“函数名(参数)”就能执行,这样主程序更短、逻辑更清楚。就像游戏里“放技能”是一个操作,按一个键就触发一套动作。
函数的定义与调用
定义格式与返回类型、参数
定义格式:返回类型 函数名(参数列表) { 函数体 }
- 返回类型:函数执行完“带回来”的值的类型。不需要带回值就写
void。 - 参数:调用时传进来的数据,如
int id表示传一个整数进来,在函数里用变量 id 来用。 - 有返回值的函数,函数体里要有
return 值;,且值的类型要和返回类型一致。
调用:在 main 或别的函数里写 函数名(实参); 就会跳去执行那个函数,执行完再回来。
void use_skill(int id) { /* 无返回值,有一个整型参数 id */
/* 释放第 id 个技能 */
}
int main() {
use_skill(1); /* 调用:传 1 给 id,执行 use_skill 里的代码 */
return 0;
}
函数声明与函数原型
为什么需要声明
如果“调用”写在“定义”前面,编译器不知道这个函数长什么样,会报错。解决办法:在文件前面先写一句声明(也叫函数原型),告诉编译器“有一个函数,返回什么类型、有几个什么类型的参数”。
声明的写法
声明格式:返回类型 函数名(参数类型); 例如 void use_skill(int); 或 void use_skill(int id); 参数名可写可不写。
数组作为函数参数
要把整个数组传给函数,形参写成 类型 数组名[] 或 类型 *数组名,例如 int hp[](hp 表示血量数组)。调用时只写数组名:heal(hero_hp); 不用加下标。函数里可以用 hp[0]、hp[1]… 访问每个元素。注意:在函数里改数组元素,会影响到原来的数组(传的是“地址”)。
局部与全局变量(了解)
在某个函数内部定义的变量叫局部变量,只在这个函数里有效,出了函数就没了。在所有函数外面定义的变量叫全局变量,整个程序都能用。类比:技能内部的临时数据 vs 全局共享的经济、蓝量。
递归(了解)
函数里面又调用自己,叫递归。要有“出口”(某一条件成立时不再调用自己),否则会无限调下去。考纲为了解即可。
本章总示例(含 main)
本章讲的是函数:自己写函数,在 main 里调用。下面是一段完整可运行的程序(自定义函数 say_skill,main 里调用两次)。
#include <stdio.h>
void say_skill() {
printf("释放技能!\n");
}
int main() {
say_skill();
say_skill();
return 0;
}
下面练习区已预填了这段代码,可修改后点击「运行」。
练习区域
提示:注释可以暂时不写,等以后学熟了再慢慢加。请仿照上面函数定义与调用在下面输入或修改,点击「运行」。
运行结果:
(点击「运行」后显示在这里)
易错知识(避免踩坑)
- 调用在定义前面却没写声明:main 里先调用了 fun(),但 fun 定义在后面,必须在前面加
void fun();声明,否则可能编译报错。 - 形参实参类型不一致:定义是
void f(int x),调用写f(3.5)会丢精度或报错,要类型匹配。 - 有返回值的函数忘了 return:函数声明成 int 却没用 return 返回值,结果是未定义的。
小结
- 函数定义:返回类型 函数名(参数) { } ;有返回值要在函数里 return 值。
- 调用:函数名(实参);调用在定义前面时要在前面加函数声明(原型)。
- 数组作参数:形参写 int a[] 或 int *a,调用时传数组名。