章节导航
指针数组与数组指针【思维壁垒】
Reid 5 分钟阅读
C/C++中指针数组与数组指针的核心区别:指针数组是装着指针的数组,数组指针是指向数组的指针,通过图解和代码示例彻底厘清这一常见思维壁垒。
指针数组与数组指针
重点关注🅰️&🅱️
- 指针数组:是一个 数组,里面装着指针。
👉 数组装指针。 - 数组指针:是一个 指针,它指向一个数组。
👉 指针指数组。
指针数组(Array of Pointers)
定义
指针数组是一个 数组,数组里的每个元素都是 指针。
例子
int a = 1, b = 2, c = 3;
int *arr[3] = {&a, &b, &c}; // 指针数组:包含三个指针的数组
arr是一个数组,长度为 3。- 这个数组里存放的是三个指向
int类型的指针,分别指向变量a、b、c。
图解
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]来访问第二行的元素,以此类推。
指针变量传递二维数组
三种方法
-
利用元素指针来传递二维数组
-
先把二维数组每行的首地址保存在一个指针数组中,再把该指针数组的首地址传给一个二级指针。~
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; } -
利用数组指针
//代码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。
总结
- 二维数组
a传递给形如double (*p)[列数]的函数。 - 指针数组
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.