c - 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的副本也存储在未知位置),副本中的数据用于减去,然后结果是存储在另一个未知位置,还是从原始变量中获取数据,减去,然后将结果存储在未知位置?
解决方案
C 中的每个表达式都会复制变量吗?
这并不重要。
编译器有优化。只要副作用相同,编译器就可以对代码做任何事情。在您的示例中p + 1;
并且a - b;
什么都不做,它们可以被编译器优化,所以什么也没有发生。
使用编译器生成的代码在实际机器上发生的事情是高度机器特定的。编译器可以首先将变量的值加载到一些寄存器,然后对这些寄存器执行计算——或者可能不执行计算,因为它们被存储,或者甚至可能不为变量保留任何内存。
我知道许多表达式不是有效的 L 值,因为最终结果的地址是未知的
这可能是您可以证明这一点的根本原因,但规则更直接。C 标准只列出运算符并说结果+
是一个值或结果*
是一个左值。没有“通用”规则。
这种复制变量并在表达式中使用副本的行为是否发生在 C 中的所有表达式上?
C 标准不谈论“变量”或“变量的副本”,C 标准谈论“值”。表达式具有定义的值、定义的最终结果。C 标准并不真正关心编译器将如何达到该值。所以实际的行为可以是任何东西。如果一个特定的编译器决定复制变量或决定不 - 对他有好处,只要最终结果是正确的。
左值是可以在运算符左侧的东西=
。不一定是变量,例如((char*)0x01)[1]
是左值,尽管它是某些运算符的结果。rvalue(或只是value)是您无法分配的值。
推荐阅读
- c# - 如何在文本框上显示接收到的 UDP 数据?
- import - Odoo 13 Enterprise的哪些应用程序可以支持与品牌生物识别机器连接:NIDEKA?
- neo4j - 如何根据ID获取特定节点的所有父节点
- azure-devops - Azure DevOps 中针对用户故事的障碍
- spring - spring jpa 查询 SQLGrammarException on join @ManyToMany
- django - 从基础模型继承模型的 FK 关联查询优化
- c - 如何使用 c 程序在 linux 中获取磁盘使用情况?
- java - 在java 8中合并recusive Hashmap
- javascript - 有什么区别?异步与嵌套承诺语句
- azure-devops - 在 Azure DevOps (ADO) 中根据草稿拉取请求自动触发拉取请求构建