C-函数调用-控制流

时间:2020-02-23 14:31:55  来源:igfitidea点击:

在本教程中,我们将学习使用C编程语言调用函数时的控制流程。

我们在函数教程中了解了函数,并在函数类别教程中了解了类别。

当我们调用或者调用一个函数时,控制流从调用函数转移到被调用函数。

例如,如果我们从main()函数调用greetings()函数,则控制流将从main()函数移至greetings()函数。
在执行greetings()或者被调用函数中的所有语句后,控制流将返回到" main()"或者被调用函数。

了解控制流程

在以下示例中,我们具有一个main(),printSquare(),getSquare()和get10()函数。

#include <stdio.h>

//function declaration
void printSquare(int);
int getSquare(int);
int get10(void);

int main(void) {
  //variable declaration
  int num;
  
  //function call
  num = get10();
  printSquare(num);
  
  return 0;
}

//function definition
void printSquare(int x) {
  int square = getSquare(x);
  printf("Square: %d\n", square);
}

int get10(void) {
  return 10;
}

int getSquare(int n) {
  return n * n;
}

让我们逐行讨论上述代码的控制流程。

首先让我们创建一个函数调用堆栈。
在此,我们将跟踪函数调用。
最初它将是空的。

函数调用堆栈

第1行。
此行将告诉编译器在我们的代码中获取stdio.h头文件。

第2行。
因此,清空行,然后移至下一行。

第3行。
单行注释。
这是给我们开发人员的,编译器将忽略它。

第4行。
该行包含printSquare()函数声明。
此函数以整数值作为参数,不返回任何值。

第5行。
该行包含getSquare()函数声明。
此函数以整数值作为参数,并返回整数值。

第6行。
此行包含get10()函数声明。
此函数不带参数,但返回一个整数值。

第7行。
空行。

第8行。
main()函数的启动。

第9行。
单行注释。

第10行。
声明了类型为int的变量num。
因此,计算机将分配内存空间来存储整数值,并以名称num引用它。

第11行。
空行。

第12行。
单行注释。

第13行。
调用get10()函数。
此时,控制流将从第13行移至第25行,其中定义了" get10()"函数。

注意!这里的main()函数是调用函数,而get10()函数是被调用函数。

因此,main()函数正在调用或者调用get10()函数。

还要注意,计算机将记住在完成" get10()"功能后必须返回到第13行。
因此,请注意此返回点。

函数调用堆栈
返回第13行

第25行。
get10()函数的启动。

第26行。
该行包含return语句,它向调用函数即main()返回整数10。

注意!在第26行,我们遇到return语句,因此控制流将移回到调用函数。

如果我们检查Function调用堆栈,可以看到我们必须返回到第13行。

函数调用堆栈
返回第13行

因此,我们将清空堆栈并返回到第13行。

函数调用堆栈

第13行。
在这一行,我们将整数值(即由get10()函数返回的10)分配给变量num。

第14行。
在这一行,我们要进行另一个函数调用。
这次我们调用printSquare()函数并传递存储在num变量中的值。

注意!在这种情况下,main()是调用函数,而printSquare()是调用函数。

因此,控制流将从第14行移至第20行,其中定义了printSquare()函数。

完成printSquare()函数后,控制流程将返回到第14行,因此,我们将在函数调用堆栈中注意到这一点。

函数调用堆栈
返回第14行

第20行。
printSquare()函数的启动。

第21行。
在这行中,我们用方名来声明一个int变量,并调用getSquare()函数并将存储在变量x中的值作为函数参数传递。

这意味着,将由getSquare()函数返回的整数值将分配给变量sqaure

因为我们正在进行函数调用,所以printSquare()函数成为调用函数,而getSqaure()函数成为被调用函数。

因此,控制流将从第21行移至第29行。
在完成调用函数的操作后,控制流将返回至第21行。
因此,让我们在函数调用堆栈中注意这一点。

函数调用堆栈
返回第21行
返回第14行

第29行。
getSquare()函数的启动。

第30行。
在这一行,我们遇到return语句。

因此,我们使用乘数*乘以乘数来计算平方,即乘以存储在变量n中的值,即10 * 10 = 100的n * n。
乘积将返回给调用函数。

此时,控制流将移回到调用函数。
因此,如果我们检查函数调用堆栈,我们可以看到我们必须返回到第21行。

函数调用堆栈
返回第21行
返回第14行

因此,我们将其弹出功能调用堆栈,然后移至第21行。

函数调用堆栈
返回第14行

第21行。
在调用了getSqaure()函数后返回了第21行,该函数返回了整数值100。
因此,该值已分配给变量sqaure

第22行,在这行中,我们使用printf()函数打印正方形。

由于这是printSqaure()函数的最后一行,因此控制流将从此处返回到调用的函数。

如果我们看一下函数调用堆栈,可以看到我们必须返回到第14行。

函数调用堆栈
返回第14行

因此,我们将返回到第14行,并将其从函数调用堆栈中弹出。

函数调用堆栈

第14行。
在调用函数后,我们回到了这一行,这里不再需要做其他操作,因此,我们移至下一行。

第15行。
空行。

第16行。
我们遇到main()函数的最后一行,该行返回0,程序执行到此结束。