基本分析
现有如下的定义:
int a[]{1, 2, 3, 4, 5};
// 定义一个指向数组的指针
int (*p1)[5] = &a;
// 定义一个指向数组元素的指针
int *p2 = a;
我们尝试打印他们的输出:
cout << p1 << endl;
cout << p2 << endl;
cout << a << endl;
得到结果:
0xa3f0fffa00
0xa3f0fffa00
0xa3f0fffa00
可以看到,三者都指向同一个地址,也就是数组a的首个元素的地址。我们再尝试解引用p1与p2:
cout << *p1 << endl;
cout << *p2 << endl;
cout << a << endl;
得到结果:
0xa2c3ff7f0
1
0xa2c3ff7f0
解引用指针p2得到a中的首个元素,而解引用指针p1 我们得到的依然是一个数组的地址,似乎是否解引用对指针p1并无影响。
遍历分析
我们尝试使用range for 语句来对三者进行分析,先尝试对p1进行遍历,因为我们在输出中发现p1指向的地址与a相同:
for (auto it : p1) {
cout << it;
}
我们发现:
error: 'end' was not declared in this scope; did you mean 'std::end'?
对p1进行解引用:
for (auto it : *p1) {
cout << it;
}
得到了正常输出的结果:
12345
再尝试对p2进行遍历:
for (auto it : p2) {
cout << it;
}
得到错误:
error: 'end' was not declared in this scope; did you mean 'std::end'?
那么我们就得到了结论:
p1、p2与a虽然指向了同一个地址,但是type不相同,我们能做的操作也不同。正如 《C++ Primer》一书中说到,type决定了你可以如何操作这些数据。虽然我们使用p2也能对数组进行遍历,但是p1是抽象层面上指向数组的指针,我们对其进行解引用,理应能做能够对数组做的一些操作,如上文中的range-for遍历。