我对地址运算符后跟解引用运算符的行为有疑问。
我们看一下表达式&*p
where 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
不是左值。
如果我们现在考虑a
与类型int[10]
,什么类型&*a
?
例如之间是否应该有区别sizeof a
and sizeof &*a
?
一方面,如果我们评估&*a
, a
会衰减到int *
使用解引用运算符,它将变成int
然后使用地址操作符int *
.
另一边如果&*a
表现得“好像两者都被省略了”,类型应该是int[10]
.
A short example https://ideone.com/7lGoB8表明 gcc 对表达式的处理方式有所不同:
#include <stdio.h>
int main(void)
{
int a[10];
printf("%zu\n%zu\n", sizeof a, sizeof &*a);
return 0;
}
Output:
40
8
这符合C11标准吗?
也许是因为“对运算符的约束仍然适用”并且解引用运算符的操作数必须是指针?
考虑从数组到指向第一个元素的指针的转换是单独发生的并且在应用之前*
。尽管在 C 实现确定它是否是以下操作数之前才决定是否将数组转换为指针sizeof
or &
(根据 C 2018 6.3.2.1 3),此转换不是*
手术。因此,当我们检查时&*
,操作数必须已经是一个指针。
此外,对操作数的约束*
运算符的特点是它应具有指针类型(C 2018 6.5.3.2 2)。因此,操作数必须是指针,而不是数组。
“结果就好像两者都被省略了一样”这句话促使我们考虑如果两者都被省略的话结果会是什么,但文本接着说“除了对运算符的约束仍然适用并且结果不是左值” ”。由于约束仍然适用,操作数must是一个指针;约束可以应用并且操作数可以是尚未转换为指针的数组,这在逻辑上是不一致的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)