int a = 1;
int* x = &a;
//-> &*x equal to &a
如果指针x
具有的地址a
并*x
指向a
' 的值,编译器无法知道它*x
指的是准确的 ,如果我通过a
,它只能知道a
' 的值*x
。
但事实证明它知道。那么这是如何工作的呢?编译器是否也传递了地址,或者*
当我&
像&*x
它一样x
或以其他方式编译时它只是取消了?
int a = 1;
int* x = &a;
//-> &*x equal to &a
如果指针x
具有的地址a
并*x
指向a
' 的值,编译器无法知道它*x
指的是准确的 ,如果我通过a
,它只能知道a
' 的值*x
。
但事实证明它知道。那么这是如何工作的呢?编译器是否也传递了地址,或者*
当我&
像&*x
它一样x
或以其他方式编译时它只是取消了?
1
, a
, x
,*x
都是表达式。
有些表达式有地址(它们被称为“左值”),有些则没有(它们被称为“右值”)。
1
是一个右值,它没有地址。所以&1
不编译。
a
是一个左值,所以它确实有一个地址。
*x
也是一个左值,所以它也有一个地址。这就是语言的工作方式。它可以用不同的方式制作(*x
可能是一个右值),但它是一个左值,因为有可用的地址很方便。
对于 operator , and&
之间没有区别,因为两者具有相同的值类别(都是左值)。a
*x
您似乎已经假设(即使不知道术语)只有变量名是左值(只有它们有地址),但事实并非如此。
关于&(*x)
, from C11
, 第 6.5.3.2 章,
一元运算
&
符产生其操作数的地址。如果操作数具有 type类型,则结果具有指向 type 的类型指针。如果操作数是一元运算符的结果,则该运算*
符和该&
运算符都不会被计算,并且结果好像两者都被省略了,除了对运算符的约束仍然适用并且结果不是左值。[...]
形式的表达&*p
有一些特殊的考虑。它不是通过首先评估*p
和获取那个地址来评估的,而是通过&
和*
取消来简单地产生p
。
这使您可以编写类似
#include <iostream>
int main() {
int* p = nullptr;
int* q = &*p;
std::cout << p << q;
}
没有任何未定义的行为。