章节导航

指针数组与数组指针【思维壁垒】

Reid 5 分钟阅读

C/C++中指针数组与数组指针的核心区别:指针数组是装着指针的数组,数组指针是指向数组的指针,通过图解和代码示例彻底厘清这一常见思维壁垒。

指针数组与数组指针

重点关注🅰️&🅱️

  • 指针数组:是一个 数组,里面装着指针。
    👉 数组装指针
  • 数组指针:是一个 指针,它指向一个数组。
    👉 指针指数组

指针数组(Array of Pointers)

定义

指针数组是一个 数组,数组里的每个元素都是 指针

例子

int a = 1, b = 2, c = 3;
int *arr[3] = {&a, &b, &c};  // 指针数组:包含三个指针的数组
  • arr 是一个数组,长度为 3。
  • 这个数组里存放的是三个指向 int 类型的指针,分别指向变量 abc

图解

arr[0] → 指向 a (值为 1)
arr[1] → 指向 b (值为 2)
arr[2] → 指向 c (值为 3)

访问元素

要访问指针数组中指针指向的值,可以这样:

cout << *arr[0] << endl;  // 输出 1
cout << *arr[1] << endl;  // 输出 2
cout << *arr[2] << endl;  // 输出 3

数组指针(Pointer to an Array)

定义

数组指针是一个 指针,它指向一个 数组

例子

int arr[3] = {1, 2, 3};
int (*p)[3] = &arr;  // 数组指针:指向一个包含 3 个 int 的数组的指针
  • p 是一个指向数组的指针,它指向 arr 这个数组。
  • p 指向的是整个数组,而不是单个元素。

图解

p → [ 1, 2, 3 ]  (整个数组)

访问元素

要访问数组指针指向的数组中的元素,可以这样:

cout << (*p)[0] << endl;  // 输出 1
cout << (*p)[1] << endl;  // 输出 2
cout << (*p)[2] << endl;  // 输出 3

🅰️关于int (*p2)[5][5]的理解

——指针数组中的常量表达式理解

这里的[5]代表了什么含义,是个数的意思吗?像int a[5]中的[5]代表了数组a中有5个元素

在C或C++语言中,int (*p2)[5] 这个声明表示 p2 是一个指向包含5个整数的数组的指针。这里的 [5]不表示数组中的元素个数,而是表示指针 p2 指向的数组中的元素类型是一个包含5个整数的数组。

具体来说:

  • int (*p2)[5] 声明了一个名为 p2 的指针,它指向的是一个数组,这个数组的每个元素都是 int 类型,并且每个这样的数组包含5个 int 类型的元素。
  • 这与 int a[5] 不同,int a[5] 声明了一个名为 a 的数组,它包含5个 int 类型的元素。
  • 换句话说,p2 指向的是一个二维数组,但这个二维数组的每一行都只有5个元素。如果我们用 p2 来访问这个二维数组,我们可以这样写:p2[0][0]p2[0][1],…,p2[0][4] 来访问第一行的元素,p2[1][0]p2[1][1],…,p2[1][4] 来访问第二行的元素,以此类推。

指针变量传递二维数组

三种方法

  1. 利用元素指针来传递二维数组

  2. 先把二维数组每行的首地址保存在一个指针数组中,再把该指针数组的首地址传给一个二级指针。~double **p / double *p[]

    //代码A
    #include<bits/stdc++.h>
    using namespace std;
    
    double sum(double *p[5], int m, int n){
        double s = 0;
        for(int i = 0; i < m; i++)
            for(int j = 0; j < n; j++)
                s += *(*(p + i) + j); // 正确的指针运算
        return s;
    }
    
    int main(){
        double a[5][6];
        double *p[5]; // 指针数组,用于存储指向a的每一行的指针
    
        // 初始化指针数组,使其指向a的每一行
        for(int i = 0; i < 5; i++)
            p[i] = a[i];
    
        for(int i = 0; i < 5; i++)
            for(int j = 0; j < 6; j++)
                cin >> a[i][j];
    
        cout << sum(p, 5, 6) << endl; // 传递指针数组p
        return 0;
    }
  3. 利用数组指针

    //代码B
    #include<bits/stdc++.h>
    using namespace std;
    
    double sum(double (*p)[6], int m, int n){
        double s = 0;
        for(int i = 0; i < 5; i++)
            for(int j = 0; j < 6; j++) s += *(*(p + i) + j);
        return s;
    }
    
    int main(){
        double a[5][6];
        for(int i = 0; i < 5; i++)
            for(int j = 0; j < 6; j++)  cin >> a[i][j];
        cout << sum(a, 5, 6);
        return 0;
    }

🅱️关于a的传递

代码A

  • main 函数中,p 是一个指针数组,声明为 double *p[5],表示这个数组有 5 个元素,每个元素是一个 double 类型的指针。
  • sum 函数中,形参 p 的类型是 double *p[5],即一个包含 5 个 double* 的数组

为什么不能直接把a传给p

  • a 是一个 二维数组,类型是 double[5][6],它表示 5 行,每行 6 个 double
  • p 的类型是 指针数组,即 double *p[5],它期望的是一个包含 5 个 double* 的数组
  • 二者的类型不匹配,因此不能直接将 a 赋值给 p
    但我们可以通过将 a 的每一行的首地址赋值给 p 的每个元素来完成转换。

代码B

  • a 是一个二维数组,声明为 double a[5][6]
  • sum 函数中,形参 p 的类型是 double (*p)[6],即指向包含 6 个 double 元素的一维数组的指针

为什么能直接把a传给p

  • 在 C++ 中,数组名会退化为指针,这里 a 作为一个二维数组,传递给 sum 时退化为指向 a[0] 的指针,而 a[0] 是一个一维数组,类型为 double[6]

  • a 的类型是:double (*)[6]
    这和 sum 函数的参数类型 double (*p)[6] 完全匹配,因此可以直接将 a 传递给 sum

总结

  1. 二维数组 a 传递给形如 double (*p)[列数] 的函数。
  2. 指针数组 p 需要逐行赋值:p[i] = a[i]

Enjoyed this post?

Subscribe to get future posts by email.

By subscribing, you agree to receive email updates from this blog.