我在读《计算机系统:程序员的视角》的第三章.在《堆栈上的本地存储》一节中,书中写道:

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

我不明白为什么会这样.考虑一下书中的这个例子:

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

函数swap_add需要两个指针参数,因此caller需要在其堆栈上为局部变量arg1arg2的地址分配空间.我知道你不能有一个指针来引用寄存器,但我不明白为什么会这样.

为什么我们不能将arg1arg2存储在寄存器中,并使用&arg1&arg2来引用它们?这样做的后果是什么?这本书主要关注x86-64,但我也很想了解其他架构.

推荐答案

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

这本书区分了在主内存中为其分配了存储空间的局部变量和仅存储在寄存器中的局部变量.这并不是您在C中可以真正看到的区别,但有一些C特性会影响它.其中最主要的是应用一元运算符&来获取局部变量的地址.

原因很简单:要让&操作符获取对象的地址,该对象必须有have个地址.只有在内存中分配了存储空间的对象才会这样做.或者至少,这是这本书所依赖的假设,对于各种各样的当代和历史建筑来说,这是正确的.

还请记住,需要本地变量地址的主要原因之一是提供对它的非本地访问.例如,启用scanf()以在其中存储一个值.但当另一个函数拥有控制权时,它可以按照自己的意愿使用CPU的寄存器,但有几点需要注意,而且在大多数情况下,它并不知道调用链upstream 的其他函数可能正在如何使用这些寄存器.

这并不意味着函数不能在寄存器中保存变量的值一段时间,甚至大部分时间,但如果它被分配给内存,则有时必须从内存读取或向内存写入该值.

C++相关问答推荐

变量的const视图是否定义良好?

你能用自己的地址声明一个C指针吗?

intellisense不工作,甚至已经下载了c/c++扩展

为什么在C中设置文件的位置并写入文件,填充空字符?

从内联程序集调用Rust函数和调用约定

C中的__attributor__((aligned(4),packed))与 struct 的用法

如何使fputs功能提示错误输入并要求用户重新输入.程序停止而不是请求新的输入

在编译时参数化类型定义

为什么GDB/MI进程的FIFO循环中有read()阻塞

C中函数类型的前向声明

解决S随机内存分配问题,实现跨进程高效数据共享

强制转换变量以在 struct 中蚕食

为什么这个分配做得不好呢?

共享目标代码似乎不能在Linux上的进程之间共享

在我的函数中实现va_arg的问题

分支预测和UB(未定义的行为)

无法理解 fgets 输出

使用 GCC 将一个函数中初始化的 struct 体实例通过指针传递到 C 中的另一个函数会产生不同的结果

如何正确探测平台设备?

将字节/字符序列写入标准输出的最简单形式