在学习指针数组与数组指针一节时,了解到数组名其实是指向数组收个元素的指针。如下面代码所示
int main() {
int a[5] = {1, 2, 3, 4, 5};
cout << "*a:" << *a << endl;
cout << "*(a + 1):" << *(a + 1) << endl;
cout << "*(a + 2):" << *(a + 2) << endl;
}
对于int类型的数组a,如果定义一个int*
类型的指针p,可以使用如下语句为指针p赋值
int main() {
...
int* p = &a[0];
cout << "*(p + 1): " << *(p + 1) << endl;
cout << "*(&a[0] + 1): " << *(&a[0] + 1) << endl;
cout << "&a[0] == p: " << (&a[0] == p ? "true" : "false") << endl;
p = a;
cout << "*(p + 1): " << *(p + 1) << endl;
cout << "*(a + 1): " << *(a + 1) << endl;
cout << "a == p: " << (a == p ? "true" : "false") << endl;
cout << "a == &a[0]: " << (a == &a[0] ? "true" : "false") << endl;
}
可以用&a[0]给p指针赋值,也可以用a给指针p赋值,指针p和a都可以进行加法运算,结果也相同;并且a、&a[0]和p做比较都相同。看样子a本质上是一个指向a[0]的int*
的指针。但真的是这样吗?看看以下代码
int main() {
...
cout << "p:" << p << endl;
cout << "&p:" << &p << endl;
cout << "a:" << a << endl;
cout << "&a:" << &a << endl;
cout << "&a[0]:" << &a[0] << endl;
}
发现p、a、&a的值都是一样的;但是&p与p不相同。因为p是指针变量,&p为变量p的地址,即二级指针。但是a和&a的值是一样的,该怎么理解呢?如果a是int*
的指针,那么&a和&p应该是相同的。但结果并不如此,事实上&a被编译器解释为int (*) [5]
类型,并且不能通过&a来定义一个int**
二级指针。说明不能把a简单的当做一个int*的指针
。
我的理解是,指针的本质就是内存地址+数据类型
,在解引用时,会根据数据类型来决定读取多大的内存空间,从而生成指定类型的对象。
因此a还是一个int类型的数组,只是在对数组名a操作的时候,某些情况可以隐式数据类型转换为int*的指针。例如在对p赋值时,右值a隐式转化为左值p;并且定义了重载的运算符+/-,使数组a可以像指针一样进行运算。
而a可以看做指向数组首个元素的指针,a的值是数组首个元素的首地址。&a表示指向整个数组的指针,&a的值是指向整个数组的首地址。二者是相同的。因此也解释了a和&相同的情况。
虽然强行解释通了,但总感觉哪里不对。为什么数组名a可以像int*
的指针进行操作,而本身并不是一个int*
?