(*&) 是左值还是 r 值?
Posted
技术标签:
【中文标题】(*&) 是左值还是 r 值?【英文标题】:Is (*&a) a lvalue or a rvalue? 【发布时间】:2019-08-28 11:42:40 【问题描述】:首先,我认为是rvalue
,但以下事实改变了我的想法。
我尝试了&(*&a)
的表达式,它工作正常,但运算符&
只能与lvalue
一起使用,所以(*&a)
是lvalue
,为什么?
【问题讨论】:
&
永远不会产生左值。 *
总是这样。
【参考方案1】:
根据 C 2018 6.5.3.2 4(讨论 unary *
运算符),一元 *
的结果是一个左值:
…如果操作数指向一个函数,则结果是一个函数指示符;如果它指向一个对象,则结果是一个指定该对象的左值。...
这告诉我们*&a
是一个左值。但是问题中问的表达式是(*&a)
,所以我们必须考虑括号的影响。
6.3.2.1 2(讨论自动转换)似乎告诉我们(*&a)
被转换为*&a
中的值并且不是左值:
除非它是 sizeof 运算符、一元
&
运算符、++
运算符、--
运算符或.
运算符或赋值运算符的左操作数,否则为左值没有数组类型的转换为存储在指定对象中的值(不再是左值);这称为左值转换。
但是,6.5.1 5(讨论带括号的表达式)与此相矛盾:
带括号的表达式是主表达式。它的类型和值与无括号表达式的相同。如果不带括号的表达式分别是左值、函数指示符或 void 表达式,则它是左值、函数指示符或 void 表达式。
这是 C 标准中的一个缺陷; 6.5.1 5 和 6.3.2.1 2 相互矛盾。留给我们理解的是,专门针对带括号的表达式的 6.5.1 5 优先于更通用的 6.3.2.1 2,这就是所有 C 实现的行为方式。
因此(*&a)
是一个左值。
【讨论】:
【参考方案2】:此表达式&(&a)
无效,将不起作用。
根据 C 标准
1 一元 & 运算符的操作数应为函数 指示符,[] 或一元 * 运算符的结果,或左值 指定一个不是位域且未声明的对象 使用寄存器存储类说明符。
和
3 一元 & 运算符产生其操作数的地址。如果 操作数的类型为“type”,结果的类型为“pointer to type”。如果 操作数是一元 * 运算符的结果,也不是该运算符 也没有评估 & 运算符,结果就像两者都是 省略,除了对运算符的约束仍然适用 结果不是左值。
所以表达式&a
的结果不是左值。因此,您可能不会将运算符 &
应用于 &&a
之类的表达式。
这是一个演示程序。
#include <stdio.h>
int main(void)
int x = 10;
&( &x );
return 0;
编译器 gcc 8.3 报错
prog.c: In function ‘main’:
prog.c:7:2: error: lvalue required as unary ‘&’ operand
&( &x );
^
这个表达式*&a
是有效的,结果是一个左值。
4 一元 * 运算符表示间接。如果操作数指向一个 函数,结果是一个函数指示符; 如果它指向一个 对象,结果是一个指定对象的左值。如果 操作数的类型为“类型指针”,结果的类型为“类型”。如果 已为指针分配了无效值,则 一元 * 运算符未定义。
请记住,括号不会影响封闭表达式是否为左值。
【讨论】:
但是在 gcc 和 clang 中,表达式都可以正常工作,为什么? @Claim Yang 不,它不起作用。编译器发出错误。 对不起,我的问题似乎出了点问题。我的表达是“&(*&a)”,你帖子中的标准4回答了我的问题。谢谢。 问题中询问的表达式是(*&a)
,而不是*&a
。
@EricPostpischil 括号不影响表达式是否为左值。以上是关于(*&) 是左值还是 r 值?的主要内容,如果未能解决你的问题,请参考以下文章