# 过程、函数与参数

> 计算机科学 · CIE A-Level 9618
> 来源: https://www.owlsprep.com/zh/study/cie-9618-u11-procedures-functions-and-parameters/

本模块讲解模块化编程的核心结构：过程、函数和参数传递。你将学习CIE理论和实践考试中常考的关键区别，避免常见编程陷阱。

**先修:** [基础编程结构与语法](https://www.owlsprep.com/zh/study/cie-9618-u11-basic-programming-structure/); [变量与数据类型](https://www.owlsprep.com/zh/study/cie-9618-u11-variables-data-types/)

## 学习目标

- 区分模块化编程中的过程与函数
- 区分形参和实参
- 比较值传递和引用传递两种参数传递方式
- 为CIE考试编写带参数化子程序的正确模块化代码

## 核心区别：过程与函数

模块化编程将大型复杂程序拆分为更小、可复用的代码块，即子程序。这使得代码更易于测试、调试，且可在程序的多个部分复用。CIE A-Level计算机科学中，子程序分为两种核心类型。

**过程** — 仅执行操作，不向调用代码返回任何值的子程序。

**函数** — 执行计算，并向调用代码返回恰好一个值的子程序。

**例题:** 编写伪代码：一个打印问候语的过程，和一个计算圆面积的函数。

1. 首先，声明过程（无返回值）：
2. ```
PROCEDURE printGreeting(name: STRING)
    OUTPUT "Hello, " + name + "!"
ENDPROCEDURE
```
3. 接下来，声明函数（指定返回类型并返回值）：
4. ```
FUNCTION calculateArea(radius: REAL) RETURN REAL
    CONSTANT PI = 3.14159
    area = PI * radius * radius
    RETURN area
ENDFUNCTION
```
5. 调用时，过程直接产生输出，而函数返回一个可存储的值：`myArea = calculateArea(5)` 会将结果存储在`myArea`中。

> **exam_tip**
>
> 在CIE伪代码中请始终使用正确关键字：只有需要返回值时才用`FUNCTION`，否则使用`PROCEDURE`，避免失分。

## 形参与实参

参数是传入子程序的输入，让子程序可适配不同的值。CIE考试经常考察形参和实参的区别，这通常是1-2分的理论题。

**形参（形式参数）** — 子程序定义中声明的占位变量，在子程序运行时存储输入值。

*例:* 在`FUNCTION calculateArea(radius: REAL)`中，`radius`就是形参。

**实参（实际参数）** — 调用子程序时传入的具体值或变量。

*例:* 在`myArea = calculateArea(5)`中，`5`就是实参。

**例题:** 找出以下代码中的形参和实参：`PROCEDURE addScore(studentID: INTEGER, newScore: INTEGER)` ... `addScore(currentStudent, 95)`

1. 形参出现在子程序定义中：`studentID` 和 `newScore`。
2. 实参是调用子程序时传入的内容：`currentStudent`（存储实际ID的变量）和`95`（字面分数值）。

## 参数传递：值传递与引用传递

这是CIE 9618理论考试中最常考的知识点之一，几乎每套试卷1都会出现。核心区别在于：子程序内部对参数的修改如何影响原变量。

**值传递** — 为子程序创建实参值的副本供其使用。对形参的修改不会影响调用代码中的原变量。

**引用传递** — 传递原实参的引用（内存地址）。对形参的修改会改变调用代码中的原变量。

**例题:** 预测以下代码在两种传递方式下的输出：
```
DECLARE y : INTEGER
y = 10
PROCEDURE changeValue(x : INTEGER)
    x = x * 2
ENDPROCEDURE
CALL changeValue(y)
OUTPUT y
```

1. 如果是值传递：会创建`y = 10`的副本赋值给`x`。将`x`改为20只会修改副本，输出为`10`。
2. 如果是引用传递：`x`指向和`y`相同的内存地址。将`x`改为20会更新原变量值，输出为`20`。

> **exam_tip**
>
> 跟踪输出时请务必检查参数传递方式——这几乎是考题中的陷阱点。

## 返回值与使用场景

**概念自测**

测试你目前的掌握程度：

1. 以下哪项是函数的定义特征？

   - 它永远不能接受参数
   - 它总是会向调用代码返回一个值
   - 它只能使用引用传递
   - 它不可复用

   *答案:* 它总是会向调用代码返回一个值

   *解析:* 正确！函数的定义特征就是返回值，这一点和过程不同。

2. 如果你在子程序内部修改一个值传递的参数，原变量会发生什么？

   - 原变量会被修改
   - 只有参数的副本会被修改
   - 程序会抛出错误
   - 实参改变，形参不变

   *答案:* 只有参数的副本会被修改

   *解析:* 正确！值传递传递的是副本，因此只有副本被改变。

**例题:** 编写交换两个整数的子程序，你需要使用哪种参数传递方式？

1. 我们需要修改原有的两个变量，因此应使用两个参数都按引用传递的过程（CIE伪代码中用`REF`标记）：
2. ```
PROCEDURE swap(a: INTEGER REF, b: INTEGER REF)
    temp = a
    a = b
    b = temp
ENDPROCEDURE
```
3. 如果使用值传递，原变量不会改变，因此交换无法生效。如果只需要返回一个值，则应使用函数。

## 常见错误

- **错误做法:** 将过程当作函数使用，把它的输出赋值给变量
  - 原因: 过程不返回值，这种写法会导致语法/运行时错误，在实践考试中会失分
  - 正确做法: 需要从子程序获取返回值时使用函数，仅执行无返回的操作时使用过程
- **错误做法:** 预测输出时混淆值传递和引用传递
  - 原因: 考试有意考察这个区别，这是代码跟踪题中最常见的失分点
  - 正确做法: 记住：值传递只改变值（副本），引用传递改变原变量（引用）
- **错误做法:** 考试答题时混淆形参和实参的角色定义
  - 原因: CIE评分标准要求正确区分参数类型才能给分
  - 正确做法: 记住：形参 = 定义中（F = 形 = 定义），实参 = 调用时（A = 实 = 调用）
- **错误做法:** 尝试从CIE伪代码的单个函数返回多个值
  - 原因: CIE A-Level伪代码中每个函数只允许一个返回值，这种写法不被接受
  - 正确做法: 如果需要修改多个值，改用带引用传递参数的过程

## 速查表

| 概念 | 核心特征 | 考试提示 |
| --- | --- | --- |
| 过程 | 无返回值，执行操作 | 使用`PROCEDURE`关键字，不要赋值结果 |
| 函数 | 返回一个值，用于计算 | 必须包含`RETURN`语句 |
| 形参 | 子程序定义中的占位符 | 出现在子程序声明中 |
| 实参 | 调用时传入的值/变量 | 出现在调用子程序时 |
| 值传递 | 传递副本，原变量不变 | 不会对调用变量产生副作用 |
| 引用传递 | 传递地址，原变量可被修改 | 交换变量或多个修改时需要 |

## 下一步

过程、函数和参数是所有模块化编程的基础，是CIE 9618试卷1（理论）和试卷2（实践）考核的核心内容。掌握参数传递对于理论题中的代码输出跟踪，以及实践考试中编写清晰可用的程序都至关重要。这些概念在你接下来学习的所有高级编程主题（从递归到面向对象编程）中都会不断使用。现在打下坚实的基础，会让后续更复杂主题的学习轻松很多。

- [文件处理](https://www.owlsprep.com/zh/study/cie-9618-u11-file-handling/)
- [面向对象编程概念](https://www.owlsprep.com/zh/study/cie-9618-u11-object-oriented-programming-concepts/)
- [声明式编程概念](https://www.owlsprep.com/zh/study/cie-9618-u11-declarative-programming-concepts/)

---

来自 [OwlsPrep](https://www.owlsprep.com) —— A-Level / IB / AP / IGCSE 免费学习指南，依据官方考纲编写。原页面：https://www.owlsprep.com/zh/study/cie-9618-u11-procedures-functions-and-parameters/
