首页 > 解决方案 > C 中的每个表达式都会复制变量吗?

问题描述

当谈到 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 之后的字符,但是这个地址新的 p+1 指针是未知的,因此不能用作 L 值。

这种制作变量副本并在表达式中使用副本的行为是否发生在 C 中的所有表达式中?例如,如果我有

    int a = 100;
    int b = 25;
    a - b;

是否创建了变量a的副本(并存储在未知位置)和创建了变量b的副本(b的副本也存储在未知位置),副本中的数据用于减去,然后结果是存储在另一个未知位置,还是从原始变量中获取数据,减去,然后将结果存储在未知位置?

标签: crvaluelvalue

解决方案


C 中的每个表达式都会复制变量吗?

这并不重要。

编译器有优化。只要副作用相同,编译器就可以对代码做任何事情。在您的示例中p + 1;并且a - b;什么都不做,它们可以被编译器优化,所以什么也没有发生。

使用编译器生成的代码在实际机器上发生的事情是高度机器特定的。编译器可以首先将变量的值加载到一些寄存器,然后对这些寄存器执行计算——或者可能不执行计算,因为它们被存储,或者甚至可能不为变量保留任何内存。

我知道许多表达式不是有效的 L 值,因为最终结果的地址是未知的

这可能是您可以证明这一点的根本原因,但规则更直接。C 标准只列出运算符并说结果+是一个值结果*是一个左值。没有“通用”规则。

这种复制变量并在表达式中使用副本的行为是否发生在 C 中的所有表达式上?

C 标准不谈论“变量”或“变量的副本”,C 标准谈​​论“值”。表达式具有定义的值、定义的最终结果。C 标准并不真正关心编译器将如何达到该值。所以实际的行为可以是任何东西。如果一个特定的编译器决定复制变量或决定不 - 对他有好处,只要最终结果是正确的。

左值是可以在运算符左侧的东西=。不一定是变量,例如((char*)0x01)[1]左值,尽管它是某些运算符的结果。rvalue(或只是value)是您无法分配的值。


推荐阅读