eve*_*ode 25 c standards addressof indirection c-preprocessor
我正在玩,gcc并尝试了以下一些代码:
int A = 42;
int *B = &A;
int *C = &*B;
Run Code Online (Sandbox Code Playgroud)
并且C == &A,正如所料.但是当我尝试:
int *B = NULL;
int *C = &*B;
Run Code Online (Sandbox Code Playgroud)
原来C == NULL,没有段错误.因此,在获取其地址之前&*B实际上并未解除引用B.
我的猜测是预处理器剥离出来的情况下,&*和*&之前,他们甚至得到了编译器,因为他们否定对方,但我无法找到任何文件,以验证这是否是标准ç或编译器特定的.
被预处理器剥离出来&*,并*&和我可以期待从任何给定的编译器这种行为?
Sha*_*our 31
这不会被预处理器剥离,&*只是最终等同于指针本身,我们可以通过草拟C99标准 6.5.3.2 地址和间接操作符第4段来看到这一点,其中说:
一元*运算符表示间接.如果操作数指向函数,则结果是函数指示符; 如果它指向一个对象,则结果是指定该对象的左值.如果操作数的类型为''指向类型'',则结果的类型为''type''.如果为指针分配了无效值,则unary*运算符的行为未定义.87)
和脚注87说:
因此,&*E等效于E(即使E是空指针),[...]
第3段说(强调我的):
一元&运算符产生其操作数的地址.如果操作数具有类型''type'',则结果具有类型''指向类型''的指针.如果操作数是一元*运算符的结果,则不会对该运算符和&运算符进行求值,结果就好像两者都被省略,除了对运算符的约束仍然适用且结果不是左值.
更新
值得注意的是gcc,clang您可以使用-E标志(请参阅实时)和Visual Studio / EP(请参见实时)查看预处理的结果.
此外,值得注意的是,正如MSalters在他的评论中所说,只有两个令牌&*不足以理解上下文,正如他的例子所示:
int *p, *q ;
int foo = *p & *q ;
Run Code Online (Sandbox Code Playgroud)
因此&*,在预处理阶段甚至不可能删除,因为您没有足够的信息来确定运算符&的地址还是按位和运算符.
Eri*_*hil 10
预处理器不会遗漏&*.但是,C 2011标准在6.5.3.2 3中说,关于&:
如果[的操作数& ]是一元的结果*操作,既没有操作者,也没有与操作员进行评价,其结果是因为如果两者都省略,不同的是在运营商的限制仍然适用,且结果不是左值.
根据上述约束的要求,*的操作数必须具有指针类型.因此,本条款&*3未改变3; 它违反了约束,因为3没有指针类型.另外,由于结果不是左值,&*x因此没有完全改变x.例如,这是不允许的:
int a, *x;
x = &a; // Normal, allowed.
&*x = &a; // Not allowed; `&*x` does not became exactly the same as `x`.
Run Code Online (Sandbox Code Playgroud)