程序使用栈内存来记住函数返回的位置,每一个c程序都由栈控制其函数执行的流程。几乎所有计算机编程语言都采用这个方案。
栈的调用规则
①当一个函数被调用时,这条调用之后的行编号就被压入调用栈。这个行编号就是“返回位置”(RL),这是在调用函数结束后(即返回)之后程序继续执行的地方。 ②如果相同的函数在不同行被调用,那么这个调用都有一个相应的返回位置(每个函数调用之后的那行)。 ③当一个函数结束之后,程序将从储存在调用栈顶部的行编号处继续。调用栈顶部的内容就会被弹出。 ④如果函数有实参,那么实参是储存在返回位置之上的。 ⑤如果函数有局部变量,那么局部变量被储存在实参之上 ⑥如果一个函数返回了一个值,这个值就回被写到调用函数栈帕的一个局部变量中,这个变量的地址(叫做值地址)储存在调用栈中。 ⑦实参和返回值共同构成了被调用函数的栈帕。
swap()函数分析
|
|
我们知道,上面的那个swap()函数是不能实现将a,b交换的功能的,当swap()函数被调用的时候,a和b的值就被复制给了实参x和y,调用栈的情况如下:
栈帕(stack) | 标识符(identifier) | 地址(address) | 值(value) |
swap | z | 106 | -(未知值) |
y | 105 | 2 | |
x | 104 | 1 | 返回位置 | 103 | 第15行 |
main | b | 102 | 2 |
a | 101 | 1 |
x的值被储存在临时变量z中,之后y的值被赋值给x,z的值赋给了y,这三步之后,在swap()函数内x和y的值确实交换了,但是在swap()中第7行代码结束之后,并在栈帕出
栈之前,栈内存是这样的:
栈帕(stack) | 标识符(identifier) | 地址(address) | 值(value) |
swap | z | 106 | 1 |
y | 105 | 2 | |
x | 104 | 1 | 返回位置 | 103 | 第15行 |
main | b | 102 | 2 |
a | 101 | 1 |
当swap()函数结束之后,顶帕出栈,栈内存就变成了:
栈帕(stack) | 标识符(identifier) | 地址(address) | 值(value) |
main | b | 102 | 2 |
a | 101 | 1 |
swap()函数被调用完成,由上面的栈内存可以看出,a和b的值并没有改变。swap()函数并没有在main()函数中起作用。C语言程序在 调用函数时使用“按值调用”的方式,这意味着值是从调用函数复制到被调用函数的实参中,这也是C语言函数调用的唯一方式。为此,C语言通过创建指针的概念来解决这个问题。