函数调用

当一个函数的名称在表达式中被提到时,这个函数就被调用了。在名称后面应该有一对括号,在括号中标明了函数参数对应的自变量(如果其定义中有一个参数列表的话),用逗号隔开。

稍后,我们将看到 函数指针 类型,可用于创建指向具有特定特征的函数的变量,然后调用时使用这个变量(而不是函数名)。

继续 Fibo 函数的例子,让我们从 OnStart 函数调用它。为此,让我们创建一个 f 变量来存储计算结果数,并在其初始化表达式中指定 Fibo 函数的名称和一个整数(例如 10)作为自变量(放在圆括号中)。

void OnStart()
{
   int f = Fibo(10); 
   Print(f); // 89
}

我们不需要创建一个变量来接收函数的值。相反,您可以从表达式中直接调用该函数,例如 "2*Fibo(10)" 或 "Print(Fibo(10))"。那么它的值将在调用时被代入表达式。这里引入了辅助变量 f,用于在单独的语句中实现调用操作和返回值。

调用过程包括以下步骤:

  • 暂停调用 (OnStart) 函数的语句序列的执行;
  • 自变量的值进入被调用函数 (Fibo) 的输入参数 n
  • 开始执行其语句;
  • 执行完成时,它将结果返回(记得包含 return 语句);
  • 结果被写入变量 f
  • 之后,继续执行 OnStart 函数,也就是将数字打印到日志中 (Print)。

对于每一次函数调用,编译器都会生成辅助二进制代码(程序员不需要为此操心)。此代码的思想是,在调用函数之前,它将程序中的当前位置推送到栈上,而在调用完成之后,检索这个位置并将它返回到函数调用之后的语句。如果一个函数调用另一个函数,而后者再调用另一个函数(即第二个函数调用第三个函数),以此类推,所有被调用函数层次结构中转换的返回地址都在栈上累积(栈因此而得名)。随着嵌套函数调用的处理,栈将以相反的顺序被清除。注意,栈也为每个函数的局部变量分配内存。