&的行为其次是*运算符 [英] Behavior of & followed by * operator

查看:48
本文介绍了&的行为其次是*运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对地址运算符后跟取消引用运算符的行为有疑问.

让我们看一下表达式& * 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 ./p>

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

一方面,如果我们评估& * a ,则 a 会使用解引用运算符衰减为 int * ,它将变为 int ,然后加上操作符的地址,然后是 int * .

另一方面,如果& * a 表现为好像都被省略了",则类型应为 int [10] .

简短的示例显示gcc对待表达式的区别在于:

  #include< stdio.h>int main(无效){int a [10];printf(%zu \ n%zu \ n",sizeof a,sizeof& * a);返回0;} 

输出:

  408 

这是否符合C11标准?

也许是因为运算符上的约束仍然适用"并且取消引用运算符的操作数必须是指针吗?

解决方案

请考虑从数组到指针到第一元素的指针的转换分别发生在应用 * 之前.尽管直到C实现确定它是 sizeof 还是& 的操作数时才做出是否将数组转换为指针的决定(根据C 2018 6.3.2.1 3),此转换不是 * 操作的一部分.因此,在我们检查& * 时,操作数必须已经是一个指针.

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

结果好像都被省略了"这样的措辞促使我们考虑如果两个都被省略了,那么结果将是什么,但是文本继续说除了对运算符的约束仍然适用并且结果是不是左值."由于约束仍然适用,因此操作数必须是指针;在逻辑上不能一致地施加约束,并且操作数可能是尚未转换为指针的数组.

I have a question about the behavior of the address-of operator followed by a dereference operator.

Let's take a look at the expression &*p where p is of type int *.

The C11 standard (section 6.5.3.2) says:

The unary & operator yields the address of its operand. If the operand has type ‘‘ type ’’, the result has type ‘‘pointer to type ’’. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue.

With the footnote:

Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2)). It is always true that if E is a function designator or an lvalue that is a valid operand of the unary & operator, *&E is a function designator or an lvalue equal to E. If *P is an lvalue and T is the name of an object pointer type, *(T)P is an lvalue that has a type compatible with that to which T points. Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.

It is clear that &*p has to be equal to p except that &*p is not an lvalue.

If we now consider a with type int[10], what type is &*a? And should there be a difference between for example sizeof a and sizeof &*a?

On the one side if we evaluate &*a, a would decay to int * with the dereference operator it will become int and with the address-of operator then int *.

On the other side if &*a behaves "as if both were omitted" the type should be int[10].

A short example reveals that gcc treats the expression different:

#include <stdio.h>

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

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

    return 0;
}

Output:

40
8

Is this in agreement with the C11 standard?

Maybe it is because the "constraints on the operators still apply" and the operand of the dereference operator has to be a pointer?

解决方案

Consider that the conversion from array to pointer-to-first-element happens separately and before the application of *. Although the decision about whether to convert the array to a pointer is not made until the C implementation determines whether it is the operand of sizeof or & (per C 2018 6.3.2.1 3), this conversion is not part of the * operation. Thus, by the time we are examining &*, the operand must already be a pointer.

Furthermore, a constraint on the operand of the * operator is that it shall have pointer type (C 2018 6.5.3.2 2). Therefore, the operand must be a pointer, not an array.

The phrasing "the result is as if both were omitted" motivates us to consider what the result would be if both were omitted, but the text goes on to say "except that the constraints on the operators still apply and the result is not an lvalue." Since the constraints still apply, the operand must be a pointer; it is not logically consistent that the constraint could apply and the operand could be an array that has not been converted to a pointer.

这篇关于&amp;的行为其次是*运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆