为何取地址表达式(&)不属于lvalue(左值)?
C标准对左值的定义
左值是一种表达式(具有非void的对象类型),它潜在地指定一个对象;64)如果左值在求值时未指定对象,则行为未定义。当说某个对象具有特定类型时,该类型由用于指定该对象的左值指定。可修改左值是指不具有数组类型、不具有不完整类型、不具有const限定类型的左值;如果是结构体或联合体,则其任何成员(包括递归地包含的所有聚合体或联合体的成员或元素)都不具有const限定类型。
我的疑问
我想明确该定义中的哪一部分阻止了&ch这类取地址表达式成为左值。当我们获取一个对象的地址时,该地址难道不是“指定”了该对象吗(例如若有char ch,那么&ch = 10是否等价于ch = 10)?还是说&ch指定的是临时值而非对象?(是否存在临时对象这类事物?)
我的困惑最初源于阅读《Pointers on C》一书,书中给出如下解释:
优先级表显示&运算符产生的结果是右值,而右值不能用作左值。但为什么呢?答案很简单。当表达式
&ch求值时,结果存储在计算机的哪个位置?它肯定在某个地方,但你无法知道具体位置。该表达式并未标识计算机内存中的任何特定位置,因此它不是左值。
我对加粗部分感到困惑:&ch难道不是标识了ch的位置吗?
解答
核心逻辑:左值要绑定自身的可标识内存对象,而非指向其他对象
C标准里左值的核心要求是——表达式本身要能指定一个可被标识的内存对象,而不是表达式的值指向某个对象。
&ch是临时计算结果,无固定可标识的存储位置
当你计算&ch时,得到的是ch的内存地址数值,但这个数值是编译器临时生成的:它可能存在CPU寄存器里,也可能存在栈上的临时存储区,但这个存储位置是编译器自动管理的,你无法通过代码直接访问、标识或修改它。换句话说,&ch这个表达式本身并没有对应一块固定的、有明确名字的内存对象,不符合左值的定义。&ch = 10的误区
这个写法本身语法非法,因为&ch不是左值不能被赋值。退一步说,就算允许,它的含义也不是给ch赋值,而是试图把10写到&ch这个临时值所在的内存位置——这和修改ch完全是两码事。对《Pointers on C》解释的理解
书中说“&ch并未标识计算机内存中的任何特定位置”,指的是表达式自身的存储位置,而不是它的值指向的ch的位置。左值要求的是表达式本身对应一块可被标识的内存,而不是表达式的值指向某个内存。关于临时对象
C语言里确实存在临时对象,比如表达式求值过程中编译器临时分配的存储区,但这类对象是编译器管理的,你无法通过左值直接引用它们,&ch的结果就属于这类临时值。
内容的提问来源于stack exchange,提问作者user135792

