C 政府的行为,;后跟*运算符

C 政府的行为,;后跟*运算符,c,language-lawyer,C,Language Lawyer,我有一个关于运算符address后跟解引用运算符的行为的问题 让我们看一下表达式&*p,其中p的类型为int* C11标准(第6.5.3.2节)规定: 一元 & 运算符生成其操作数的地址。如果操作数的类型为“” 类型 ’’, 结果的指针类型为“” 类型 ’’. 如果操作数是一元数的结果 * 操作人员 该操作员和 & 对运算符进行求值,结果就好像两个运算符都进行了求值一样 省略,但运算符上的约束仍然适用,并且结果不是左值 加上脚注: 因此,&*E相当于E(即使E是空指针),并且&(E1[E2])

我有一个关于运算符address后跟解引用运算符的行为的问题

让我们看一下表达式
&*p
,其中
p
的类型为
int*

C11标准(第6.5.3.2节)规定:

一元 & 运算符生成其操作数的地址。如果操作数的类型为“” 类型 ’’, 结果的指针类型为“” 类型 ’’. 如果操作数是一元数的结果 * 操作人员 该操作员和 & 对运算符进行求值,结果就好像两个运算符都进行了求值一样 省略,但运算符上的约束仍然适用,并且结果不是左值

加上脚注:

因此,&*E相当于E(即使E是空指针),并且&(E1[E2])相当于((E1)+(E2))。如果E是一个函数指示符或一元运算符的有效操作数的左值,*&E是一个函数指示符或等于E的左值。如果*P是左值,T是对象指针类型的名称,*(T)P是一个左值,其类型与T指向的类型兼容。一元*运算符取消引用指针的无效值包括空指针、与指向的对象类型不适当对齐的地址以及对象在其生命周期结束后的地址

很明显,
&*p
必须等于
p
,除非
&*p
不是左值

如果现在考虑<代码> <代码> >类型<代码> int [10 ] < /代码>,什么类型是<代码> ** < /代码>? 例如

sizeof a
sizeof&*a
之间是否应该有区别

一方面,如果我们计算
和*a
a
将衰减为
int*
,使用解引用操作符,它将变成
int
,然后使用操作符的地址
int*

另一方面,如果
和*a
表现为“好像两者都被省略”,则类型应为
int[10]

简短的说明gcc对表达式的处理不同:

#include <stdio.h>

int main(void)
{
    int a[10];

    printf("%zu\n%zu\n", sizeof a, sizeof &*a);

    return 0;
}
这是否符合C11标准


可能是因为“对运算符的约束仍然适用”,并且解引用运算符的操作数必须是指针?

考虑到从数组到指向第一个元素的指针的转换是单独进行的,并且是在应用
*
之前进行的。尽管直到C实现确定数组是
sizeof
还是
&
的操作数(根据C 2018 6.3.2.1 3),才决定是否将数组转换为指针,但此转换不是
*
操作的一部分。因此,当我们检查
&*
时,操作数必须已经是指针

此外,对
*
运算符的操作数的一个约束是,它应具有指针类型(C 2018 6.5.3.2)。因此,操作数必须是指针,而不是数组


短语“结果好像是被省略”促使我们考虑如果两者都省略了结果,但是文本继续说“除了对运算符的约束仍然适用,结果不是LVal.”由于约束仍然适用,操作数<强>必须< /强>为指针;约束可以应用,操作数可以是尚未转换为指针的数组,这在逻辑上是不一致的。

有人认为不清楚。什么是不清楚的?问题是证明GCC的行为似乎不符合标准,并询问有什么错。我个人期望GCC所证明的行为,而不是建议的等效行为。
*a
有一种类型为
int
,因此我认为
&(int)可以返回
int*
。你的“可能”听起来很正确。
a
是左值,但
&a
不是左值。注意:我可以编译
void*p=&a,但不是
void*q=&(&*a)40
8