C++二级指针的用法指向指针的指针(多级间接寻址)

发布于:2025-06-24 ⋅ 阅读:(15) ⋅ 点赞:(0)

        指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。

        指针的指针就是将指针的地址存放在另一个指针里面。

        通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。        

       一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。例如,下面声明了一个指向 int 类型指针的指针:

int **var;

          当一个目标值被一个指针间接指向到另一个指针时,访问这个值需要使用两个星号运算符,如下面实例所示:

#include <iostream>
 
using namespace std;
 
int main ()
{
    int  var;
    int  *ptr;
    int  **pptr;
 
    var = 3000;
 
    // 获取 var 的地址
    ptr = &var;
 
    // 使用运算符 & 获取 ptr 的地址
    pptr = &ptr;
 
    // 使用 pptr 获取值
    cout << "var 值为 :" << var << endl;
    cout << "*ptr 值为:" << *ptr << endl;
    cout << "**pptr 值为:" << **pptr << endl;
 
    return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

var 值为 :3000
*ptr 值为:3000
**pptr 值为:3000

在 C++ 程序中,指针可以指向基本数据类型,如整型或字符型,从而允许我们访问这些数据。由于指针本身也是存储在内存中的变量,它记录着数据的内存地址,因此指针也可以指向另一个指针,即指向指针的指针。

        虽然这个概念初听起来有些复杂,但可以这样理解,指针本质上是一个存储内存地址的变量,当有一个指针变量存储了另一个指针变量所在内存的地址时,我们就称这个指针为“指向指针的指针”,又称为二级指针。

为了更清晰地展示这一概念,下面是一个实际的例子:

int N = 2;
int* pN = &N;     // 定义一个指针变量pN,记录变量N所在的内存地址
int** ppN = &pN;  // 定义一个指针变量ppN,记录指针变量pN所在的内存地址

        在这段代码中,首先定义了一个整型变量 N,然后定义了一个整型指针指向这个变量 N。换句话说,这个指针的值就是整型变量 N 在内存中的地址。最后,指向指针的指针 ppN 登场了,我们用 int** 作为数据类型定义了一个指针 ppN,其中保存的就是 pN 指针变量所在内存中的地址,也就是它指向这个整型指针 pN。

        下图展示了这三个变量之间的关系

图 1 指向指针的指针

        从图 1 中可以看到,变量 N 保存在内存地址 0016FA38 这个位置,而指针变量 pN 记录的值是 N 所在的内存位置 0016FA38,同时它自己保存在内存地址 0016FA5C 这个位置。

        同理,作为指向 pN 的指针,ppN 这个指针变量记录的值是 pN 所在内存地址 0016FA5C 的位置,而它自己保存在内存地址 0016FA90 这个位置。

        简单来讲,普通指针指向的是一个具体的数据,而指针的指针指向的是一个指针数据,我们可以把指针数据也当作某个具体的数据,它也有自己的数据类型(例如 int*),也占用一定的内存(例如 0016FA5C),记录一定的数值(例如 0016FA37)。类比普通数据,指向指针的指针的数据类型,就是在它所指向的数据的类型之后加一个“*”。

        例如,我们要定义一个指针指向另一个 int* 类型的指针,那么它自身的类型就是 int* 加一个“*”就成了 int**。而这个指针的值,同样是用“&”取得被指向的指针变量的地址赋给它,于是它就成为指向这个指针的指针。

        在 C++ 中,可以用下面的语法格式来定义一个二级指针:

数据类型** 指针变量名

其中,数据类型表示它所指向的指针的数据类型。例如:

  • int** ppN = &pN;

            这样就定义了一个指向整型指针的二级指针 ppN,它指向另一个指针变量 pN,而 pN 指针变量又指向一个整型变量。

            二级指针通常用来访问指针数组。数组不仅可以保存基本数据类型的数据,还可以保存指针,保存指针的数组被称为指针数组。如果要访问一个指针数组,使用二级指针最为方便。

// 这是一个指针数组,其中保存的是各个字符串常量的首地址指针,其类型是 const char*
const char* arrMonth[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

// 定义一个指向指针的指针
// 因为要指向的指针是 const char*类型,所以加上*后它自身的类型就是 const char**
// 这里数组的首地址 arrMonth 就是数组的第一个元素
// 也就是指向第一个字符串 “Jan” 的指针
const char** pMonth = arrMonth;

// 获取用户输入
int nIndex = 0;
cout << "请输入月份对应的数字: " << endl;
cin >> nIndex;
// 对指针进行运算,使其指向相应的数组元素
// 也就是相应的字符串指针
const char* pCurMonth = *(pMonth + (nIndex - 1));
cout << "对应的月份是: " << pCurMonth << endl;

        在以上这段代码中,arrMonth 数组中保存的是多个字符串常量的指针,这些指针的数据类型是 const char*

        为了利用指针偏移方便地访问数组中的各个字符串,我们需要一个可以指向这些字符串元素的指针,因为字符串元素的类型是 const char*,所以我们定义了一个 const char** 类型的二级指针 pMonth,并将字符串数组的首地址赋值给它,使其指向字符串数组的第一个元素。然后通过对 pMonth 进行运算,让其偏移指向数组中所对应的字符串元素。

        指针运算后得到的仍然是指针,我们需要用“*”符号取得这个指针所指向的内容,才能得到对应的字符串指针,直接输出就可以得到数字对应的月份字符串


网站公告

今日签到

点亮在社区的每一天
去签到