*运算符的行为和后跟*运算符

Osi*_*ris 15 c language-lawyer

我有一个关于address-of运算符后跟dereference运算符的行为的问题.

让我们来看看表达&*p其中p的类型的int *.

C11标准(第6.5.3.2节)说:

一元&运算符产生其操作数的地址.如果操作数具有类型''type'',则结果具有类型''指向类型''的指针.如果操作数是一元*运算符的结果,则不会对该运算符和&运算符进行求值,结果就好像两者都被省略,除了对运算符的约束仍然适用且结果不是左值.

随脚注:

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

很明显,除了不是左值之外,&*p必须等于.p&*p

如果我们现在考虑a类型int[10],是什么类型&*a?并且应该在例如sizeof asizeof &*a?之间有区别吗?

一方面,如果我们进行评估&*a,aint *使用解除引用运算符衰减它将变为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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

40
8
Run Code Online (Sandbox Code Playgroud)

这是否符合C11标准?

也许是因为"对运算符的约束仍然适用"而且解除引用运算符的操作数必须是指针?

Eri*_*hil 13

考虑从数组到指针到第一元素的转换是在应用之前单独进行的*.虽然在C实现确定它是否是操作数sizeof&(根据C 2018 6.3.2.1 3)之前,不会决定是否将数组转换为指针,但此转换不是*操作的一部分.因此,到我们检查时&*,操作数必须已经是指针.

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

措辞"结果好像两者都被省略了"促使我们考虑如果两个都被省略会得到什么结果,但文本接着说"除了对运算符的约束仍然适用且结果不是左值"由于约束仍然适用,操作数必须是指针; 约束可以应用并且操作数可以是尚未转换为指针的数组在逻辑上不一致.