1

所以我不知道为什么,但我了解到当你调用一个函数并向它传递一个参数时,它会在堆栈(处理器?)上处理它。

有人可以解释一下吗?

那么它如何改变变量、内存块等的值呢?

4

3 回答 3

2

堆栈在大多数情况下用于将参数传递给函数。使用它的原因是您不必绑定到固定的内存位置(用于参数)以使您的函数正常运行。如果您有可以从固定内存中获取参数的函数,那么您可能只有在内存空闲时才能运行它,并且您只能运行它的一个实例。Stack 让您可以随时将参数存储到程序的当前上下文中。在 x86 处理器上,有一个寄存器指向堆栈的末尾,另一个寄存器指向堆栈的开头。这些实际上只是您希望堆栈驻留的主内存的地址。

有 PUSH 指令将堆栈结束寄存器移动到下一个位置并将指定的数据(可以是来自其他寄存器的值或在某个地址或直接值)存储到堆栈结束寄存器指向的地址。另一条指令是 POP,反之亦然。这样,如果您坚持计划并跟踪您推送到堆栈的内容,您可以让您的函数在任何上下文中工作。

还有一些其他较少使用的选项来传递参数,例如通过寄存器,例如由 bios 中断使用。如果您想了解更多信息,我建议您阅读有关“调用约定”的内容。

于 2012-10-04T06:34:44.587 回答
2

不能保证参数在堆栈上传递,它取决于体系结构和编译器。

至于值和内存是如何改变的——当您调用一个必须进行调用者看到的更改的函数时,您提供的不是实际值,而是该值的(指向)地址,这是正常的。只要函数知道正确的内存位置,它就可以进行这些更改。

于 2012-10-03T13:03:03.400 回答
0

让我们从这个假设你有一个函数开始

int foo(int value) {
   int a = 10;
   return a;
}

因此,每当进行函数调用时,操作系统都需要一些内存空间来分配在这种情况下函数的局部变量以及int a在这种情况下传递给函数的参数int value。通过在堆栈上分配内存来满足此内存要求。堆栈只不过是分配给每个进程的内存区域,它实际上表现为堆栈数据结构(LIFO)。

现在问题出现了,当进行函数调用时,所有东西都存储在堆栈中。压入堆栈的第一件事是以相反的顺序传递给函数的参数(如果超过一个)。2. 然后是调用这个函数的函数的返回地址(因为一旦这个函数foo完成执行它应该返回到代码中调用它的地方) 3. 最后被调用函数的局部变量被压入堆栈.

一旦被调用函数完成执行代码,它就会返回到先前存储在堆栈中的返回地址,因此我们说函数调用完成或返回。在这种情况下,该函数有一个返回值,它将返回给被调用函数。然后该空间可以自由使用,并且可以在随后的函数调用中被覆盖。

(现在,如果您连接 dotes,您可以理解为什么函数中的局部变量(自动变量)的作用域仅限于函数调用的生命周期(您问了一个与关闭的作用域相关的 SO 问题),因为一旦调用返回内存为这些语言环境变量分配的空间已经消失(它仍然存在,但是一旦函数返回就无法访问它们),因此int a在这种情况下这些自动变量的寿命会限制到foo()返回到被调用函数。

旁注::我已经阅读了您在 SO 中发布的许多问题。我猜你正在尝试学习 C 以及底层硬件和操作系统的基本工作,而它们之间的混淆正在杀死你。除了这个问题的答案之外,我建议您阅读和理解一些指示,这将使您对所面临的问题有很多深入的了解。

  1. 对于 C 参考 K&R,这是最好的书。
  2. 在开始阅读有关操作系统概念的一点点(内存处理,特别是虚拟内存)
  3. 尝试从广义上想象一个系统的工作方式,例如不同组件的交互方式。
  4. 了解内存相关内容和系统内部的一些很好的链接http://duartes.org/gustavo/blog/best-of

如果您想深入了解函数调用的堆栈空间,请尝试此链接http://www.binarypirates.in/2011/02/17/understanding-function-stack-in-c/

希望这可以帮助

于 2012-10-09T19:49:28.150 回答