我们可以直接在“堆栈”中间获取元素吗?

时间:2018-01-27 04:56:43

标签: c memory stack local-variables

将情况想象如下。

int main(void)
{
    ...
    int a=10; //a get into the stack.
    int b=20; //b get into the stack.
    int c=30; //c get into the stack.
    ...
}

众所周知,“堆栈段”满足“堆栈数据结构”的存储方式;在这里,局部变量a,b和c精确地存储在这样的存储器方向上,因此理论上我们只能访问堆栈顶部的元素。

但是如果我们做这样的事情呢?

printf("b = %d",b);

局部变量b位于a和c的中间,但我们可以得到它。

那么......我们可以说我们可以直接将元素放在堆栈中间吗?

Here is the image of " a, b, and c stored in stack "

3 个答案:

答案 0 :(得分:2)

  

局部变量a,b和c完全存储在这样的存储器方向

我不知道你从哪里得到这个,但事实并非如此,至少在现代编译器中是这样。

首先,C本身没有指定使用堆栈的任何内容。如何实现函数调用是实现定义的。许多常见的实现使用堆栈式数据结构来实现函数调用,因为最后会调用最后一个被调用的函数。

但这并不意味着局部变量存储在堆栈结构中。编译器有很多选项,如:

  1. 如果在运行时不需要,它可以完全消除变量。
  2. 它可以将变量放在寄存器中。
  3. 它可以重新排序变量。
  4. 在所有这些情况下,编译器唯一保证代码的可观察行为不会改变。

    由于它不像数据结构那样在堆栈中存储变量,因此在中间访问它们没有问题。

答案 1 :(得分:0)

首先,C标准永远不会在任何地方发出堆栈。现在从标准实现者转移可以实现这样一种方式,即局部变量作为函数框架的一部分存储在堆栈内存中。

现在您正在考虑 - 堆栈总是在顶部访问,但在这里我们可以直接访问变量b。虽然它在某个地方的中间。不,你错了 - 事情是函数的框架存储在堆栈中并在完成时弹出(虽然实现也可以以其他方式执行 - 但一般来说)。这里的操作单元不是变量。

通过访问b,我们没有违反任何堆栈数据结构规则。功能框架是以LIFO方式访问的,而不是那些框架内的变量。

现在也有点偏离上下文这样的隔离日。我们可以简单地说它们具有自动存储持续时间。就是这样。它们也可以在寄存器组中实现(标准不会阻止它们)。功能框架可能具有堆叠数据结构行为的功能框架。

答案 2 :(得分:0)

使用堆栈存储自动变量只是一个实现细节,标准不需要任何内容​​。但在较低的层面上,它确实是最常见的实现。这是因为在处理器中,一个特殊的寄存器(堆栈指针)用于存储函数调用中的返回地址(指令调用和返回)。当自动变量也存储在该堆栈中时,在返回时或块结束时回收存储器是微不足道的。但它们并没有被单独压入堆栈:帧指针用于存储当前块的内存区域(包括上层帧的引用),并且堆栈指针在包含所有帧的大小的单个操作中增加局部变量。然后通过当前帧指针的偏移来知道这些变量。因此,他们以自己的地址而不是堆栈元素而闻名。