我试图了解C中的表达式的R值和L值,并且我知道许多表达式不是有效的L值,因为最终结果的地址未知。这是因为在许多情况下,表达式中使用了变量的副本,因此该副本的地址未知。例如,
char ch = 'a';
char *p = &ch;
p + 1; //This expression can be used as an R-value, but not an L-value
我相信表达式中正在发生的事情(如果我错了,请纠正我)是创建了p的副本,在该副本中添加了1,以便p + 1指向ch之后的char,但是地址这个新的p + 1指针的未知,因此不能用作L值。
对于C中的所有表达式,是否都会制作变量的副本并在表达式中使用副本的行为?例如,如果我有
int a = 100;
int b = 25;
a - b;
是已创建变量a的副本(并存储在未知位置)和已创建变量b的副本(b的副本也存储在未知位置),副本中的数据用于减去,然后减去结果存储在另一个未知位置,还是从原始变量中减去数据,然后将结果存储在未知位置?
此类计算的实现不是标准的,因此它们在不同的编译器中可能会有所不同。要了解的重要一点是R值表示临时值。它可以是寄存器或某些已分配的内存。
在CPU中通过寄存器进行计算。因此,编译器会将变量的值移入寄存器,然后计算减法。这是这种计算的集合:
659: c7 45 f8 64 00 00 00 movl $0x64,-0x8(%rbp)
660: c7 45 fc 19 00 00 00 movl $0x19,-0x4(%rbp)
667: 8b 45 f8 mov -0x8(%rbp),%eax
66a: 2b 45 fc sub -0x4(%rbp),%eax
您可以看到值100(十六进制为64)和25(十六进制为19)保存在堆栈中相对于基本指针的地址(分别为-0x8,-0x4)。然后将-0x8中的值移到eax寄存器中,然后从寄存器中的值中减去-0x4中的值并存储在寄存器本身中。
如您所见,结果将最终在寄存器中,因此它在存储器中没有地址。