C编译器如何确定有效的左值?

C编译器如何确定有效的左值?,c,pointers,variable-assignment,lvalue,C,Pointers,Variable Assignment,Lvalue,我试图弄清楚C如何确定表达式是否是有效的左值 我知道声明变量会给它一个命名的内存空间,也就是变量名。变量名可以是右值或左值。如果用于表示一个值,则使用其内容,但如果将其用作左值,则使用其地址告知右侧的表达式存储在此地址中。我看到的这个操作的图片类似于ADDRESS=VALUE:赋值运算符的右表达式和左表达式就是这样计算的 那么为什么我不能定义像inta,然后使用运算符的地址在该地址中存储值,如&a=5 我知道&a返回一个常量指针,但这意味着我不能更改地址或无法更改存储在地址中的值?如果其内容无法

我试图弄清楚C如何确定表达式是否是有效的左值

我知道声明变量会给它一个命名的内存空间,也就是变量名。变量名可以是右值或左值。如果用于表示一个值,则使用其内容,但如果将其用作左值,则使用其地址告知右侧的表达式存储在此地址中。我看到的这个操作的图片类似于
ADDRESS=VALUE
:赋值运算符的右表达式和左表达式就是这样计算的

那么为什么我不能定义像
inta
,然后使用运算符的地址在该地址中存储值,如
&a=5

我知道
&a
返回一个常量指针,但这意味着我不能更改地址或无法更改存储在地址中的值?如果其内容无法更改,那么为什么使用
*&a=5
有效

为什么我不能这样赋值,尽管左手表达式总是按照我理解的地址计算?也许我的理解有问题?

自动左值转换 C 2018第6.3.2.1.2节对此进行了说明,其中规定:

除非它是
sizeof
运算符的操作数、一元
&
运算符、
++
运算符、
--
运算符或
运算符的左操作数或赋值运算符,否则没有数组类型的左值将转换为存储在指定对象中的值(并且不再是左值);这称为左值转换

考虑表达式
x=y+z

  • y
    +
    的操作数。
    +
    运算符不在上述异常列表中。因此
    y
    被转换为其值
  • z
    +
    的操作数。
    +
    运算符不在上面的异常列表中。因此
    z
    被转换为其值
  • x
    是赋值运算符
    =
    的左操作数。这在上面的异常列表中。因此
    x
    仍然是左值
关于
&a=5
关于
int a;
后接
&a=5;

  • &
    运算符的结果仅仅是一个地址,它只是一个值;没有对象保存此值,因此它不是左值
  • 赋值运算符必须有一个左值作为其左操作数。C 2018 6.5.16 2是一个约束,表示“赋值运算符应具有一个可修改的左值作为其左操作数。”
因此,
&a=5;
违反了约束,需要C编译器为其生成诊断消息。
=
运算符不能将普通值作为其左操作数

可以设计一种编程语言,使赋值运算符接受
&a=5;
,并使用它将右边的值存储在左边给定的位置。BLISS语言可以做到这一点。在BLISS中,变量的名称始终提供其地址。要获取值,必须在变量前面加上句点(其作用类似于C的一元运算符
*
)因此,C不这样做是为了美观和方便,而不是为了逻辑上的必要性。在C中,左值在大多数地方都会自动转换为值,例外情况是作用于对象而不是值的运算符。在BLISS中,必须显式指定每个lv值到值的转换

关于
*a=5
*&a=5
中:

  • 根据C 2018 6.5.3.2 4,“一元
    *
    运算符表示间接。如果操作数指向函数,则结果为函数指示符;如果操作数指向对象,则结果为指定对象的左值…”

因此,
*&a
提供赋值运算符所需的左值。

首先,C不使用术语rvalue,而使用术语lvalue,它的意思是()

[…]可能指定对象的表达式(对象类型不是void)

它并不意味着对象的地址,它意味着左值就是对象

&
的操作数通常也是左值

  • 一元
    &
    运算符的操作数应为函数指示符、
    []
    或一元
    *
    运算符的结果,或指定非位字段且未使用寄存器存储类说明符声明的对象的左值
  • 结果是一个指针类型表达式的值,一个地址。即使地址指向一个对象,它也不是该对象。就像华盛顿特区宾夕法尼亚大道西北1600号是一个地址,但它不是在该地址找到的建筑物一样

    如果你有房子:

    house my_House;
    
    你可以问它的地址

    &my_house;
    
    这是您房子的地址,但它不是房子,即不是左值,但位于您房子地址的房子是房子,即左值:

    *&my_house;
    

    这在不同的操作员之间是不同的。对于操作员的要求或结果没有一致的规则。因此,您的问题太广泛了,因为为了回答这个问题,我们必须用C语言写一篇关于所有操作员的文章,基本上是复制/粘贴标准第6.5章。“地址=值”是错误的“图片”。如果有什么区别的话,它相当于“*ADDRESS=VALUE”来告诉您分配给特定的内存地址。只写“ADDRESS=VALUE”表明变量的地址已更改…但您不能更改变量的地址。它的位置在变量的生命周期内是固定的。感谢您的回复,伙计们,可能是&ge运算符