“想多了看到的都是问题;做多了看到的都是答案!”
在C++中,多维数组是由一系列连续的内存单元组成的。为了访问这些内存单元,可以使用指针。指针是一个变量,其值为内存地址。可以使用指针来访问内存中存储的数据。
include <iostream>
using namespace std;
int main() {
int a[3][4] = {
{7,2,3,4},
{5,6,7,8},
{9,1,2,3}};
// 尽管 在下面定义的指针里,p、k、t、j 的值,是一样的,
int (*p)[3][4] = &a; // 指针p指向对象的数据结构为:数组对象a
int (*k)[4] = a; // 指针k指向对象的数据结构为:数组对象a[0]
int (*t)[4] = &a[0]; // 指针t指向对象的数据结构为:数组对象a[0]
int *j = &a[0][0]; // 指针j指向对象的数据结构为:数组对象a[0][0]
// 但是 由于指向的数据结构不同,"+1"的含义是不同的!
cout<<p+1<<endl;
cout<<k+1<<endl;
cout<<t+1<<endl;
cout<<j+12<<endl;
return 0;
}
下面分别输出了 p、k、t、j 的值 和 p+1、k+1、t+1、j+12 的值 :
由于指针所指对象的数据结构不同:"+1"的含义有所不同:对象a占4×12=48字节(0x30),对象a[0]占4×4=16字节(0x10),对象a[0][0]占4×1=4字节(0x04)。
解析指针指向基本元素的层级也不同:
p // 对象a的地址
*p // 对象a[0]的地址 (等价于 k、t )
**p // 对象a[0][0]的地址(等价于 j )
所以:
cout<<***p<<endl; // 输出:7
cout<<**k<<endl; // 输出:7
cout<<**t<<endl; // 输出:7
cout<<*j<<endl; // 输出:7
最后,当定义一个指针(无论指向数组的哪里,只要不出数组的范围)时,可向前(+1)或向后(-1)。如下:
#include <iostream>
using namespace std;
int main() {
int a[3][4] = {
{7,2,3,4},
{5,6,7,8},
{9,1,2,3}};
// ###################################
int (* p)[3][4] = &a;
int (*k)[4] = a; // 数组名a自动转化为:&a[0]
int (*t)[4] = &a[1];
int *j = &a[2][1];
// ###################################
cout<<p<<":"<<***p<<endl;
cout<<k+1<<":"<<**(k+1)<<endl;
cout<<t-1<<":"<<*(*t-1)<<endl;
cout<<""<<endl;
cout<<j-5<<":"<<*(j-5)<<endl;
cout<<j-4<<":"<<*(j-4)<<endl;
return 0;
}
运行结果:
参考资料:
- 《C++ Primer(第5版)中文版》王刚 杨巨峰 译