【问题标题】:Are temporary values like operands of arithmetic operators put in the stack?算术运算符的操作数等临时值是否放入堆栈?
【发布时间】:2011-01-25 15:04:43
【问题描述】:

我想知道当我使用以下算术运算符时内存中会发生什么:

int i;
i = 5 + 3;

是否会临时自动将值 5 和 3 放入堆栈(例如自动为它们创建一些静态变量)?我想它们需要存在于某个地方才能进行添加,那么在哪里?

当涉及到函数调用时会发生什么?

i = 5 + f(3);

传递给 f 的参数 3 是否存储在某个地方?那么 f 的返回值(比如 f 返回一个 int)呢?

非常感谢,

【问题讨论】:

  • 我认为这取决于目标架构,以及它的操作码是否支持立即值作为操作数。
  • 确实,这取决于。但不仅如此,还有更多:编译器今天的感觉、f 的调用约定、月相、优化设置等。这是你不应该尝试的级别如果你珍惜时间和理智,那就比编译器更聪明。

标签: c memory stack


【解决方案1】:

您的第一个示例将在编译时进行评估(请参阅http://en.wikipedia.org/wiki/Constant_folding),所以我们忽略那个。

在类似i = f(3) + g(5) 的情况下,编译器对于如何实现它有很多选择,具体取决于您正在使用的特定平台。它可以将东西放入寄存器、堆栈,甚至其他地方,只要它认为合适。

【讨论】:

  • 实际上,如果编译器关心 ABI 兼容性(它通常会关心,除非另有说明),调用约定指示如何管理返回值(在 x86 上的 cdelc 的情况下,返回值应该在 EAX 寄存器中,比如 wiki)。
  • @delnan:对于函数调用,是的。不适用于本地操作。即便如此,如果函数是内联的,调用约定就变得无关紧要了。
【解决方案2】:

C 规范不要求将这些值放入内存。该实现可以将它们保存在寄存器中,并且永远不会将它们存储在内存中以执行加法,或者编译器甚至可以将5 + 3 重写为8,并且在运行时根本不进行任何加法。任何真正的实现都是这样的。

在语言理论中,实际上53 并不是指内存。它们是值(而不仅仅是表示可以从中获取值的位置)。您可以通过尝试编写&5 轻松看到这一点。它不起作用 - 您无法收到地址。

【讨论】:

    【解决方案3】:

    查看编译器开关。可能有可能保留/生成中间汇编代码。在那里你可以清楚地看到你的代码会发生什么。

    【讨论】:

      【解决方案4】:

      编译器会根据需要分配临时变量。这是在编译/优化时完成的。不在运行时(无论如何,对于 C 程序)。对于您的示例,最有可能的结果是

      5 + 3
      

      5 + f(3)
      

      将存储在一个寄存器中,并将寄存器的值复制到 i 的位置。

      【讨论】:

        【解决方案5】:

        当你有 i = 5 + 3 这样的表达式时,不需要将操作数放在堆栈上。编译器会将其翻译成类似于:

        mov eax, 5                   // load first operand
        add eax, 3                   // compute the sum
        mov [ebp - 4], eax           // and store it
        

        指令中的操作数是硬编码的。一些编译器可能会决定将这段代码写成int i = 8

        i = 5 + f(3)

        在这种情况下,3 将被压入堆栈,因为必须调用 f,但它的返回值(通常)存储在 eax 中。这个汇编代码可能是一个很好的翻译:

        push 3                      // f's argument
        call f                      // call f, return value is in eax
        add eax, 5                  // compute the sum
        mov [ebp - 4], eax          // and save in i
        

        【讨论】:

          猜你喜欢
          • 2021-12-23
          • 2015-02-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-08
          • 1970-01-01
          • 2022-11-04
          • 1970-01-01
          相关资源
          最近更新 更多