8. 二级指针
二级指针就是指向指针的指针。
前面我们学习了指针,它是一个变量,它的内部保存的是所指向的变量的地址。那么有没有一个变量能够指向一个指针呢?答案就是二级指针。
在说二级指针之前我们先来说一下指针取地址运算符(&)。
当我们有个变量如下:
int x = 100;
变量 x 的类型是 int,当我们对变量 x 取地址时,表达式 &x 返回的值是一个数字代表内存地址,表达式返回的类型是 int*,我们为了保存这个 int* 类型的数值我们需要定义一个 int* 类型的指针。如下面代码所示。
int *px = &x;
现在我们程序中已经声明了两个变量 x 和 px。现在我们对变量 px 取地址,表达式 &px的返回值依旧是一个地址,但因为 px 的类型为 int*,当我们再次取地址为 &px时,要在 int*类型的基础上再加一个星号才是 &px 的类型,表示为 int**。我们要在程序中保存这个地址,需要定义一个 int** 类型的变量,这个变量就是二级指针。代码表示如下:
int ** ppx = &px;
变量 ppx 就是二级指针,它保存了 变量 px 的地址。
那么如何使用这个二级指针呢?答案是解引用。当对指针 ppx 一次解引用(*ppx)则得到的是它指向的变量 px ,如果对 *ppx 再次解引用(**ppx)则得到了 px 指向的变量 x。即:*ppx 为变量 px 的引用, **ppx 为变量 x 的引用。
让我们写一个完整可运行的示例来看一下吧。
// filename: pointer_to_pointer.c
#include <stdio.h>
int main(int argc, char *argv[]) {
int x = 100;
int *px = &x;
int ** ppx = &px;
// 打印三个变量的值
printf("x:%d, px:%p, ppx:%p\n", x, px, ppx);
// 打印三个变量的地址
printf("&x:%p, &px:%p, &ppx:%p\n", &x, &px, &ppx);
// 打印两个指针解引用后的值
printf("*px:%d, *ppx:%p\n", *px, *ppx);
// 打印指针ppx 二次解引用后的值
printf("**ppx:%d\n", **ppx);
return 0;
}
运行结果如下:
weimingze@mzstudio:~$ gcc -o pointer_to_pointer pointer_to_pointer.c
weimingze@mzstudio:~$ ./pointer_to_pointer
x:100, px:0x7ffe58bc0af4, ppx:0x7ffe58bc0af8
&x:0x7ffe58bc0af4, &px:0x7ffe58bc0af8, &ppx:0x7ffe58bc0b00
*px:100, *ppx:0x7ffe58bc0af4
**ppx:100
从上述运行结果可知 变量 px 保存的是 x 的地址, ppx 保存的是 px 的地址。
通过解引用运算符 *ppx 的值为 0x7ffe58bc0af4, 即 *ppx 就是 px 的引用。 **ppx 的值为 100, 即 **ppx 就是 x 的引用。
二级指针同一级指针一样遵循着指针的各种运算规则。
基于以上原理,同样还可以有三级指针、四级指针、…… 。只是我们很少使用罢了。
实验:
尝试使用二级指针对多个一级指针和多个变量进行操作。