何为指针

上节提到了,C++ 中每一个变量都拥有一个地址(类似网址的存在)。比如:

#include <iostream>
using namespace std;
int main() {
    short a{42};
    int b{5};
    int c{76};
    char d{'A'};
    long long e{1LL};
    // [...]
}

那么会有:

Variable Storage

这里,灰色的一长排就是计算机的存储空间。其中每一个小方格代表一字节,而我们定义的变量 a 到变量 e 就会存放在这些存储空间里面。由于变量的类型不同,所以它们所需要的存储空间也不同。这里,每一个变量存放的位置就称为它的地址(Address)。比如变量 a 存放在了内存空间 0x62fe08 的位置上,那么就说变量 a 的地址为 0x62fe08;其余同理。

一般地,地址是一个十六进制的数。变量的声明顺序和存储顺序是反着的,因为自动存储期的变量是通过栈来存储的。这些变量所代表的存储空间并没有紧密地挨在一起是因为有对齐要求。

我们借此机会再回顾一下变量的概念:变量就是指明计算机中的一段存储空间的东西。可以说,变量相当于给一段确定地址的存储空间加一个名字,从而之后可以通过这个名字来访问这段存储空间里的数据。概括一下就是:变量由三个要素构成:名字、地址和数据。

var

取地址与解地址

我们可以通过一个叫做“取地址运算符”的东西来获取变量的地址。

运算符名称作用
&a取地址运算符取得 a 在存储空间中的地址

比如:

#include <iostream>
using namespace std;
int main() {
    short a{42};
    int b{5};
    int c{76};
    long long e{1LL};
    cout << &a << endl;    
    cout << &b << endl;
    cout << &c << endl;
    cout << &e << endl;    
}

上述代码将变量 a b c e 的地址输出。

在不同的环境下,变量存储的位置可能并不一致;所以上述代码的运行结果可能各有差异。

输出 char 型变量的地址会出现不符合预期的现象,我们将在后面的章节解释其原因。

这些地址其实还可以保存到变量中去。比如对于 int 类型变量 c 的地址 &c,我们可以用一种称为 int* 的类型去保存:

int* address{&c};

int* 这种,用于保存地址的变量称为指针(Pointer),而用于保存地址的类型称为指针类型(Pointer type)。

那读者可能要问了,这样一个保存地址的变量有什么用呢?其实它的用处很大。比如你可以通过一个叫做“解地址运算符”的东西去获得这个地址中存放的变量。

运算符名称作用
*a解地址运算符取得地址 a 中存放的变量

比如:

#include <iostream>
using namespace std;
int main() {
    int c{76};
    int* address{&c};         // 变量 address 保存了 c 的地址
    cout << *address << endl; // 将地址 address 中存放的值输出
}

这里就会输出 address 这个地址中存放的内容。address 是变量 c 的地址,因此 *address 相当于获得了 c 这个变量,最后输出它。

通过解地址运算符,你还可以做更多的事情:

#include <iostream>
using namespace std;
int main() {
    int c{76};
    int* address{&c};
    (*address) = 42;
    cout << c << endl;
}

这里仍然把 address 声明并定义为 c 的地址。这时,我们首先把 address 解地址,然后给它赋值——就相当于给 c 赋值;最后输出 c,发现 c 的值确实改变了。这个例子表明,我们通过指针可以通过指针来改变一个变量的值。

最近更新:
代码未运行