指针数组和数组指针的区别及其详解
引言
对于指针数组和数组指针的概念,相信很多人经常会感到迷惑,见到二者一时不能分辨究竟对应哪一个才是对的。接下来我们来分析一下二者区别。
我们来看一下这个示例代码:
int *ptr1[10];
int (*ptr2)[10];
对于上述代码语句,你是否能分清哪一句代码声明的是指针数组,而哪一句代码声明的又是数组指针呢?
答案是第一行代码声明的ptr1是一个指针数组,数组名为 ptr1,而“int*”修饰的是数组的内容,该数组包含 10 个指向 int 类型数据的指针。第二行代码声明的 ptr2 则是一个数组指针,指针变量名为 ptr2,而 int 修饰的是数组的内容,即数组的每个元素。即ptr2 是一个指针,它指向一个包含 10 个 int 类型数据的数组。要想进一步弄清楚二者区别,我们接着看后边内容。
一、指针数组和数组指针的概念
-
指针数组: 指针数组可以说成是”指针的数组”,首先这个变量是一个数组,其次,”指针”修饰这个数组,意思是说这个数组的所有元素都是指针类型,在32位系统中,指针占四个字节。
-
数组指针: 数组指针可以说成是”数组的指针”,首先这个变量是一个指针,其次,”数组”修饰这个指针,意思是说这个指针存放着一个数组的首地址,或者说这个指针指向一个数组的首地址。
二、指针
为进一步理解指针数组和数组指针,我们回顾一下指针:
int var = 20; //var是变量,普通变量存放的是实际的值
int *p; //*p是指针,指针变量存放的是地址
p = &var; //p的值是var的地址,指针变量的值是具有实际值的变量的地址
*p = 10;
cout<< var <<endl;;
上述代码执行结果为10。
其中,指针变量有类型,即指针存放的地址指向的数据类型。“ * ”用来访问指针的值所表示的地址上的变量;“&”用来取得变量的地址;此时,我们可以得到*p=var,它们完全等价,具体原理可以写成:
*(访问指针的值所记录的地址)+p(p的地址)=var
考虑一下代码:
#include<iostream>
using namespace std;
int main() {
int arr[5] = { 1, 2, 3, 4, 5 };
int *ptr = arr; //ptr指针指向数组第0个元素的地址
cout<< ptr <<endl;
return 0;
}
再考虑如下声明:
int (*ptr)[5];
ptr指针指向一个大小为5的int型数组,由于[]的优先级高于*,因此加小括号即可让指针指向整个数组。ptr的类型是“指向数组中5个整数的指针”。
三、C/C++运算符优先级
为了更进一步方便看清代码意义,分解代码变量声明内容,我们来看一下C/C++中运算符的优先级。从上到下,从左到右,优先级一次减弱。
从上述表中我们可以看到,()、[]、* 的运算级优先级依次递减。
因此,对于指针数组来说,[] 的运算级高于 * 的运算级,则现有数组,再有指向数组元素的指针。而对于数组指针,() 运算级最高,先执行圆括号中的 * 获得指针,然后再让指针指向整个数组。
四、示例代码解析
在进行上述了解之后,我们再来看一下下边的示例代码:
int arr[3]={1,2,3};
int (*p1)[3] = &arr;
注意第二行代码写法,下述写法是错误的:
int (*p2)[3] = arr;
在上面的示例代码中,&arr 是指整个数组的首地址,而 arr 是指数组首元素的首地址。虽然第二种写法是错误的,所表示的意义不同,但二者之间的值却是相同的。为什么语句“int(*p1)[3]=&arr”是正确的,而语句“int(*p2)[3]=arr”却在有些编译器下会报错呢?
究其原因,在 C/C++ 中,对于变量的类型有严格要求,其涉及的变量类型是强类型模式。赋值符号“=”号两边的数据类型必须是相同的,如果不同,则需要显示或隐式类型转换。在这里,p1 和 p2 都是数组指针,指向的是整个数组。p1 这个定义的“=”号两边的数据类型是一致的,而 p2 这个定义的“=”号两边的数据类型则不一致(左边的类型是指向整个数组的指针,而右边的数据类型是指向单个字符的指针),因此会提示错误信息。
更多推荐
所有评论(0)