r值存储在c中的哪里?

在C中,我有这个代码片段:

int a; a = 10 + 5 - 3 

我想问一下:(10 + 5-3)存放在哪里? (据我所知, a位于堆栈上, (10+5-3)怎么样?这个rvalue如何计算?)

通常,r值被“存储”在程序本身内。

换句话说,编译器本身( 在程序运行之前 )计算10 + 5 – 3值(它可以这样做,因为它全部基于常量立即值),并且它发出汇编代码来存储结果此计算中的任何l值(在这种情况下,名为a的变量,编译器可能知道该变量是数据段原点的相对地址)。

因此,只有在程序的二进制内部,在看起来像的汇编指令中找到值为12的r值

  mov , $0C 

$ 0C是“r值”。

如果r值恰好是只能在运行时进行的计算的结果,那么如果底层c代码是:a = 17 * x; // x某些运行时间var,r值也将被“存储”(或更确切地说是物化)为程序二进制文件中的一系列指令。 上面简单的“mov dest,imm”的区别在于它需要几个指令来将变量x加载到累加器中,乘以17并将结果存储在变量a所在的地址。 编译器可能“授权自己”;-)将堆栈用于某些中间结果等,但这样就可以了
a)完全依赖于编译器
b)transiant
c)并且通常仅涉及部分 r值
因此可以肯定地说,r值是编译时概念,它封装在程序的某些部分(而不是数据)中,并且不存储在程序二进制文件中的任何地方。

回应paxdiablo:上面提供的解释确实限制了可能性,因为c标准实际上没有规定任何性质。 从来没有,大多数任何r值最终都会实现,至少在某种程度上是通过一些设置的指令实现的,这样无论是计算的(运行时)还是正确的值都能得到正确的处理。

常量可能在编译时被简化,因此您提出的问题可能无济于事。 但是,比如说i - j + k确实需要在运行时根据某些变量进行计算,可能会在编译器喜欢的任何地方“存储”,具体取决于CPU架构:编译器通常会尝试尽力使用寄存器,例如

  LOAD AX, i SUB AX, j ADD AX, k 

计算这样的表达式将其“存储”在累加器寄存器AX中,然后将其分配给具有STORE AX, dest等的某个存储器位置。 如果一个现代优化编译器在一个甚至半体面的CPU架构上(是的,包含x86! – )需要将寄存器溢出到内存中以获得任何相当简单的表达式,我会感到非常惊讶!

这取决于编译器。 通常,值(12)将由编译器计算。 然后将其存储在代码中,通常作为加载/移动立即汇编指令的一部分。

它存储的地方实际上完全取决于编译器。 该标准并未规定此行为。

通过实际编译代码并查看汇编器输出可以看到一个典型的位置:

 int main (int argc, char *argv[]) { int a; a = 10 + 5 - 3; return 0; } 

产生:

  .file "qq.c" .def ___main; .scl 2; .type 32; .endef .text .globl _main .def _main; .scl 2; .type 32; .endef _main: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %eax movl %eax, -8(%ebp) movl -8(%ebp), %eax call __alloca call ___main movl $12, -4(%ebp) ;***** movl $0, %eax leave ret 

相关位被标记;***** ,您可以看到该值由编译器创建,并直接插入到mov类型指令中。

请注意,它只是这么简单,因为表达式是一个常量值。 一旦引入非常量值(如变量),代码就会变得有点复杂。 那是因为你必须在内存中查找这些变量(或者它们可能已经在寄存器中),然后在运行时而不是编译时操作这些值。

至于编译器如何计算值应该是什么,这与表达式评估有关,并且是另一个问题:-)

  • RHS(右侧)中的计算结果由编译器在称为“常量传播”的步骤中计算。
  • 然后,它被存储为汇编指令的操作数,将值移动到a

这是MSVC的反汇编:

  int a; a = 10 + 5 - 3; 0041338E mov dword ptr [a],0Ch 

您的问题基于错误的前提。

C中左值的定义属性是它在存储中有一个位置,即它被存储 。 这就是左值与右值的区别。 Rvalue 存储在任何地方。 这就是使它成为右值的原因。 如果它被存储,根据定义它将是左值

术语“左值”和“右值”用于将表达式世界二等分。 也就是说, (10+5-3)是恰好是rvalue的表达式(因为你不能对它应用&运算符 – 在C ++中规则更复杂)。 在运行时,没有表达式,左值或右值。 特别是,它们不存储在任何地方。

您想知道值12的存储位置,但值12既不是左值也不是右值(与表达式12相反,它将是一个右值,但12不会出现在您的程序中)。