题
在C中,我有此代码文章:
int a;
a = 10 + 5 - 3
我想问:(10+5-3)存储在哪里? (我所知道的, a
位于堆栈上,怎么样 (10+5-3)
?该rvalue如何计算?)
解决方案
通常,R值被“存储”在程序本身中。
换句话说,编译器本身(在程序运行之前)计算10 + 5-3值(可以这样做,因为它都是基于恒定的即时值),并且它发出了汇编代码以将本计算的结果存储在分配的任何l值中(在此,案例,该变量命名为a,编译器可能是对数据段来源的相对地址)。
因此,在程序的二进制中仅发现了一个价值12的R值,该集合指令中 看起来 喜欢
mov <some dest, typically DS-relative>, $0C
$ 0C是“ R-Value”。
如果R-value恰好是只能在运行时完成的计算结果,则说基础C代码是否为:A = 17 * X; // x一些运行时间var,R值也将被“存储”(或更确切地说是实现)作为程序二进制中的一系列说明。上面简单的“ mov dest,imm”的区别在于,将使用几个指令将变量x加载到蓄能器中,乘以17并将结果存储在变量a IS的地址处。编译器可能“授权自身” ;-)将堆栈用于某些中间结果等。但是,这就是
a)完全依赖编译器
b)跨性别者
c)通常只涉及 部分 R-Value
因此,可以肯定地说,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
您的问题是基于不正确的前提。
定义属性 LVALUE 在C中,它在存储中有一个位置,即 存储. 。这就是区分LVALUE rvalue. 。 rvalue是 不是 存储在任何地方。这就是使它成为rvalue的原因。如果存储了,那将是 LVALUE 根据定义。
术语“ lvalue”和“ rvalue”用于表达式世界。那是, (10+5-3)
是恰好是rvalue的表达式(因为您不能将其应用于它 - 在C ++中,规则更为复杂)。在运行时,没有表达式,lvalues或rvalues。特别是,它们没有存储在任何地方。
您想知道该值12存储在哪里,但是值12既不是lvalue也不是rvalue(与表达式相反 12
这将是一个rvalue,但是 12
没有出现在您的程序中)。