在堆栈中,存储器可以以LIFO方式存储 我将向您展示一个清楚解释我的问题的例子
public static void main()
{
int i=0;
char ch='a';
string s="doubt";
}
在上面的例子中,第一个堆栈存储'i'值,并存储在'store'值的顶部,并存储在''值'商店的顶部。现在的问题是,如果我想使用'i'值,它怎么能弹出来。如果它弹出所有变量以获得int'i'值,那么's'和'ch'值可以存储在哪里
答案 0 :(得分:1)
Java实现通常将源代码编译为某个JVM字节码。 C#实现针对CLI进行编译,即CLR名为CIL的字节码。
JVM bytecode用于基于堆栈的计算机。 CIL字节码也是stack-based。所以JVM和& CIL字节码以某些stack machine为目标(但对于Java -i.e.JVM-和C#-i.e.CIL - 则不同)。
编译器会计算局部变量集并生成适当的指令来处理call stack中的当前帧。
从概念上讲,当控制流离开block声明它时,会弹出局部变量的槽(在当前调用帧中)(但实际上发生的是实现细节)。阅读scope。所以你不需要显式地弹出任何值(编译器会处理嵌套的作用域和局部变量)。
通常,在function prologue中调用期间会调用(在调用堆栈上)调用帧,并在(对应的)函数结尾中弹出(来自调用堆栈),但详细信息取决于{ {3}}
JVM需要calling conventions,CIL也需要garbage collector。它将扫描堆栈上的指针(对象)(在您的示例中为s
)
调用堆栈确实是遵循stack规则的last-in first-out,但是拉取和弹出操作是调用协议的一部分,并且是编译器生成的,因此保持隐式。在呼叫期间,在呼叫栈上推送新的呼叫帧。返回时,它会从调用堆栈中弹出。另请阅读tail-calls(然后在通话时新呼叫帧替换当前的呼叫帧);遗憾的是,JVM一般不支持尾调用。
我建议阅读SICP,其中有一些章节解释了这些概念。它是一个优秀的免费可用的编程介绍(不使用Java或C#作为其编程语言)。
答案 1 :(得分:1)
在上面的示例中,第一个堆栈存储'i'值,并存储在'store'值的顶部,并存储在''值'商店的顶部。
正确。请注意,您没有说'推',这是不正确的。
现在的问题是,如果我想使用'i'值,它怎么能弹出来。
它不是'弹出'。它是通过当前堆栈帧基础的索引访问的。
如果弹出所有变量以获得int'i'值
没有。
可以存储's'和'ch'值的位置
在堆栈上,或者更好地在当前堆栈帧中。
您应该将堆栈视为堆栈 frames 的堆栈,每个方法调用一个,而不是作为值堆栈。