c语言 - 我们可以直接获得"stack"中间的元素吗?



将情况考虑如下。

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 的中间,但我们可以得到它。

所以。。。我们可以说我们可以直接在堆栈中间获取元素吗?

这是"a、b和c存储在堆栈中"的图像

局部变量 a、b 和 c 完全存储在这样的内存方向上

我不知道你从哪里得到这个,但这不是真的,至少在现代编译器中是这样。

首先,C 本身没有指定任何关于使用堆栈的内容。函数调用的实现方式是实现定义的。许多常见的实现使用类似堆栈的数据结构来实现函数调用,从某种意义上说,最后一个调用的函数将首先返回。

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

  1. 如果在运行时不需要变量,它可以完全消除变量。
  2. 它可以将变量放在寄存器中。
  3. 它可以对变量重新排序。

在所有这些情况下,编译器唯一能保证代码的可观察行为不会改变。

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

首先,C 标准从不在任何地方说堆栈。现在从标准开始 - 实现者可以实现这样一种方式,即局部变量作为函数框架的一部分存储在堆栈内存中。

现在你在想 - 堆栈总是在顶部访问,但在这里我们可以直接访问变量b。虽然它在中间的某个地方。不,你错了 - 问题是函数的框架存储在堆栈中并在完成后弹出(尽管实现也可以以其他方式做到这一点 - 但一般来说)。变量不是这里的操作单元。

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

而且现在这样隔离的日子有点断章取义。我们可以简单地说它们具有自动存储持续时间。仅此而已。它们也可以在寄存器组中实现(标准不会阻止它们)。函数帧是可能具有堆栈数据结构行为的函数帧。

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

最新更新