为什么创建局部变量的指针需要过程在堆栈上分配空间?

问题描述 投票:0回答:2

我正在读《计算机系统:程序员的视角》的第三章。在“堆栈上的本地存储”部分中,书上说:

到目前为止,我们看到的大多数过程示例不需要任何超出寄存器可以保存的本地存储。然而,有时本地数据必须存储在内存中。常见的情况包括:地址运算符“&”应用于局部变量,因此我们必须能够为其生成地址。

我不明白其中的原因。考虑一下书中的这个例子:

long caller()
{
    long arg1 = 534;
    long arg2 = 1057;
    long sum = swap_add(&arg1, &arg2);
    long diff = arg1 - arg2;
    return sum * diff;
}

函数

swap_add
需要两个指针参数,因此
caller
需要在其堆栈上为局部变量
arg1
arg2
的地址分配空间。我知道你不能有一个指针来引用寄存器,但我不明白其中的原因。

为什么我们不能将

arg1
arg2
存储在寄存器中并使用
&arg1
&arg2
来引用它们?这样做的后果是什么?这本书重点介绍 x86-64,但我也很想了解其他架构。

c x86-64 computer-science
2个回答
0
投票

为什么我们不能将

arg1
arg2
存储在寄存器中并使用
&arg1
&arg2
来引用它们?

因为CPU寄存器不存储在主存中,因此没有任何与之关联的内存地址。您可以将它们视为位于 CPU 本身内的非常快的专用内存单元。因此,如果您需要本地声明的任何变量的地址,则必须使用堆栈存储而不是寄存器来使该变量具有内存地址。

使用内存地址的操作完成后,可以将值放回到寄存器中。这就是为什么通常每当编译器看到

&
运算符时,它都需要在内存中的某个位置分配变量。

如果编译器足够聪明,注意到使用

&
运算符不会对其他变量产生副作用,并且变量的地址不会转义当前函数,那么它也可能会决定将该变量保留在注册并简化
&
操作,但那是另一回事了。


0
投票

为什么创建局部变量的指针需要过程在堆栈上分配空间?

本书区分了在主内存中为其分配存储空间的局部变量和仅存储在寄存器中的局部变量。这并不是您在 C 中实际看到的区别,但有一些 C 功能会影响它。其中最主要的是应用一元

&
运算符来获取局部变量的地址。

原因很简单:要让

&
运算符获取对象的地址,该对象必须一个地址。只有在内存中分配了存储空间的对象才会这样做。或者至少,这是本书所依赖的假设,并且对于各种当前和历史建筑来说都是如此。

还要记住,需要局部变量地址的主要原因之一是提供对其的非本地访问。例如,启用

scanf()
来在其中存储值。但是,当调用另一个函数时,它可以按照自己的需要使用 CPU 的寄存器,但有一些注意事项,并且在大多数情况下,它不知道调用链上的其他函数可能如何使用它们。

© www.soinside.com 2019 - 2024. All rights reserved.