C 政府的行为,;后跟*运算符
我有一个关于运算符address后跟解引用运算符的行为的问题 让我们看一下表达式C 政府的行为,;后跟*运算符,c,language-lawyer,C,Language Lawyer,我有一个关于运算符address后跟解引用运算符的行为的问题 让我们看一下表达式&*p,其中p的类型为int* C11标准(第6.5.3.2节)规定: 一元 & 运算符生成其操作数的地址。如果操作数的类型为“” 类型 ’’, 结果的指针类型为“” 类型 ’’. 如果操作数是一元数的结果 * 操作人员 该操作员和 & 对运算符进行求值,结果就好像两个运算符都进行了求值一样 省略,但运算符上的约束仍然适用,并且结果不是左值 加上脚注: 因此,&*E相当于E(即使E是空指针),并且&(E1[E2])
&*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)似乎这就是答案。忽略它们并不意味着它们从未出现过,数组类型会违反约束。不,这只是意味着在数组中它们没有被忽略。@EugeneSh。它们被省略,但操作数的类型已经是每个约束的指针。无论如何,因为它是一个数组,所以不管是否省略它们(无论是否求值,它都是有效的,与空情况不同)。@Acorn No.约束不会更改类型。运算符求值。@EugeneSh“约束不会更改类型。运算符求值会更改类型。”或者,您可以说“运算符会更改类型”。也就是说,无论运算符是否求值,都是运算符更改了类型。
40
8