在C中,我有这个代码片段:
int a;
a = 10 + 5 - 3
Run Code Online (Sandbox Code Playgroud)
我想问一下:(10 + 5-3)存放在哪里?(据我所知,a位于堆栈上,怎么样(10+5-3)?这个rvalue如何计算?)
通常,r 值“存储”在程序本身中。
换句话说,编译器本身(在程序运行之前)计算 10 + 5 - 3 值(它可以这样做,因为它全部基于常量立即值),并发出汇编代码来存储结果这个计算在赋值的任何 l 值中(在这种情况下,名为 a 的变量,编译器可能知道它是各种数据段源的相对地址)。
因此,r值,其具有12的值只发现了程序的二进制内,一个装配指令内看起来像
mov <some dest, typically DS-relative>, $0C
Run Code Online (Sandbox Code Playgroud)
$0C 是“r 值”。
如果 r 值恰好是只能在运行时完成的计算的结果,假设底层的 c 代码是:a = 17 * x; // x 一些运行时变量,r 值也将作为程序二进制文件中的一系列指令“存储”(或者更确切地说是具体化)。与上面简单的“mov dest, imm”不同的是,将变量x加载到累加器中,乘以17并将结果存储在变量a所在的地址需要几条指令。可能的是,编译器可以“授权本身” ;-)使用堆栈一些中间结果等,但这样将是
一个)完全编译器相关的
b)中transiant
c)和典型地将只涉及部分的r值的
因此可以肯定地说,r 值是一个编译时概念,它被封装在程序的一部分(不是数据)中,并且不存储在程序二进制文件中的任何地方。
回应paxdiablo:上面提供的解释确实限制了可能性,因为c标准实际上并没有规定任何这种性质的东西。无论如何,大多数任何 r 值最终都会被实现,至少部分是通过一些指令设置的,以便正确的值,无论是计算(在运行时)还是立即得到正确处理。
常量可能在编译时被简化,因此您提出的问题可能无济于事.但是,比如说,i - j + k确实需要在运行时从某些变量计算,可以"存储"在编译器喜欢的任何地方,具体取决于CPU架构:编译器通常会尽力使用寄存器,例如
LOAD AX, i
SUB AX, j
ADD AX, k
Run Code Online (Sandbox Code Playgroud)
计算这样的表达式将其"存储"在累加器寄存器AX中,然后将其分配到某个存储器位置STORE AX, dest等.如果一个现代优化编译器在一个甚至半体面的CPU架构上(是的,包含x86! - )需要将寄存器溢出到内存中以获得任何相当简单的表达式,我会感到非常惊讶!