函数
掌握函数「黑箱」思想:封装、高内聚低耦合、形参实参、值传递 vs 地址传递!
一、函数就是黑箱:使用者 vs 设计者
| 角色 | 关注点 | 不需要关心 |
|---|---|---|
| 使用者 | 函数名、参数、返回值 | 内部实现 |
| 设计者 | 功能实现、封装、可维护 | 调用者场景 |
设计目标:高内聚、低耦合——函数只干一件事,接口简洁。
在C语言中,函数意味着功能模块。一个典型的C语言程序,就是由一个个的功能模块拼接起来的整体。也因为如此,C语言被称为模块化语言。
对于函数的使用者,可以简单地将函数理解为一个黑箱,使用者只管按照规定给黑箱一些输入,就会得到一些输出,而不必理会黑箱内部的运行细节。
二、函数定义语法四要素
返回类型 函数名(形参列表)
{
函数体;
return 返回值;
}
| 要素 | 说明 | 示例 |
|---|---|---|
| 返回类型 | void 表示无返回 |
int / double / char * |
| 函数名 | 见名知意,小写+下划线 | int max(int x, int y) |
| 形参列表 | 调用时由实参初始化 | (int *buf, int len) |
| return | 立即退出函数 | return; 或 return z; |
语法汇总:
a.当函数的参数列表为 void 时,表示该函数不需要任何参数。
b.当函数的返回类型为 void 时,表示该函数不返回任何数据。
c.关键字 return 表示退出函数。
- ①若函数头中规定有返回数据类型,则
return需携带一个类型与之匹配的数据; - ②若函数头中规定返回类型为
void,则return不需携带参数。
三、形参 vs 实参 · 一一对应
概念
- 函数调用中的参数,被称为实参(调用时被实际传递出去的参数),即 arguments
- 函数定义中的参数,被称为形参(只是一个形式并无实际数据出现),即 parameters
实参与形参的关系:
- 实参与形参的类型和数量必须一一对应。
- 形参的值由实参初始化。
- 形参与实参位于不同的内存区域,彼此独立。
内存关系演示
#include <stdio.h>
void demonstrate_params(int param1, int param2)
{
printf("函数内 - 形参地址:\n");
printf("¶m1 = %p, param1 = %d\n", ¶m1, param1);
printf("¶m2 = %p, param2 = %d\n", ¶m2, param2);
}
int main(void)
{
int arg1 = 10, arg2 = 20;
printf("主函数 - 实参地址:\n");
printf("&arg1 = %p, arg1 = %d\n", &arg1, arg1);
printf("&arg2 = %p, arg2 = %d\n", &arg2, arg2);
printf("\n调用函数时:\n");
demonstrate_params(arg1, arg2);
return 0;
}
四、参数传递两种方式
① 值传递(Copy)
void swap_val(int x, int y)
{
int tmp = x; x = y; y = tmp; // 仅修改副本
}
int main(void)
{
int a = 1, b = 2;
swap_val(a, b); // a,b 保持原值
}
② 地址传递(Pointer)
void swap_addr(int *x, int *y)
{
int tmp = *x; *x = *y; *y = tmp; // 通过地址改原件
}
int main(void)
{
int a = 1, b = 2;
swap_addr(&a, &b); // a,b 被成功交换
}
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 只读大结构体 | const struct *p |
避免大拷贝 |
| 需要修改实参 | 地址传递 | 直接操作原件 |
| 简单只读标量 | 值传递 | 简洁安全 |

浙公网安备 33010602011771号