2

据我了解,每个线程通常只获得一个堆栈(而进程中的所有线程通常共享一个堆)。我一直认为堆栈用于在函数调用发生时存储程序计数器(PC)的值。但后来我在某处读到某些变量类型,例如integerorboolean也被分配到堆栈上。既然栈上的值是通过严格的 FILO 方式管理的,那么如何随时检索这些变量呢?

例如,在声明 之后int a, b, c;,我可以在它们的范围内随时以任何顺序对这些变量做任何我想做的事情。这是怎么做到的?为什么 value 不在c堆栈顶部并因此隐藏 values a, b

4

3 回答 3

1

调用堆栈也用于局部变量,也用于将参数传递给函数。

您是对的,“值类型”是在堆栈上传递的,而引用类型是在堆上分配的,但是当引用类型用作参数时,指向该堆位置的指针仍将在堆栈上传递。

尽管堆栈通常被“感知”为 LIFO 缓冲区,但也有与调用堆栈相关的帧或基指针,可用于直接访问当前堆栈指针上方或下方的内存。这就是函数仍然可以在不更改堆栈指针的情况下随机访问参数的方式。

这张来自 Wikipedia 的图表可能有助于可视化这一点,但请注意,许多人会认为堆栈应该“向下”增长。

此处的这篇博文解释了英特尔调用堆栈

于 2012-09-05T16:44:09.490 回答
1

首先,我建议您应该对堆栈进行更多研究(请参阅WikipediaStack Explanation以及其他通过谷歌搜索/CS 书籍)。

但是,对于您的具体问题,所有不是堆生成的变量都在堆栈上。这通常包括您在未直接堆分配的特定函数中定义的任何内容(通过newC++ 和 Java 中的运算符)。在某些语言中,所有内容都是堆分配的,只有指向这些堆结构的指针存储在堆栈中(就像在 Python 中一样)。您将看到各种语言之间的这些细微变化。

因此,您关于整数和布尔值始终在堆栈上的陈述是不正确的。如果您在函数中定义它们,它们在堆栈上,如果您使用构建它们,它们在堆上new。请注意,对于 Java,如果您使用int原语,它通常是基于堆栈的,而Integer对象是基于堆的——但这是 Java 超出基本堆栈知识的更高级的细微差别。

您可以int a, b, c;在同一范围内访问所有变量,因为它为该函数堆栈范围内的所有 3 个变量腾出了空间。当函数返回时,这些变量会随着堆栈向上移动而被清除。在那之前,所有 3 个都存在,因为整个作用域块同时是堆栈的 FILO 结构的一部分,并且将持续存在直到您返回。

于 2012-09-05T16:47:35.357 回答
1

这个问题有很多答案,具体取决于您在什么环境中工作。当然,您不应该将处理器堆栈(与机器代码 POP 和 PUSH 一起使用)指令与堆栈(或更正确的堆栈帧)使用类似于 python 解释器或 .net 运行时

但简短的回答是堆栈的顶部只是一个内存位置,所以你只需使用偏移量

如果你按 a,b,c

所以 b 的地址将是堆栈地址 - 4。

于 2012-09-05T16:50:48.150 回答