浅析数组与指针的联系与区别2

有时候遇到声明几个相同类型的指针的情况,我们能否像声明相同变量那样声明一个数组呢?答案是肯定的。我们会很自然的写成,比如int *p[3],但是偶然我们发现别人的程序里有int (*p)[3]的出现,这两者是否相同呢?答案是否定的。下面将通过一个例子说明这两者的区别和联系,为了方便对照下面把解释写在代码的注释中。

#include <iostream>
using namespace std;

int main()
{	
	int arr[3] = {0,1,2};

	/*[]的优先级比*的高,所以先p1[3],后*。这样就不难理解为什么是3个指针变量*/
	int *p1[3];//声明3个(注意是3个)int类型的指针

	/*加()后,先运算(*p2),可人为的理解为先声明一个指针变量p2,然后指向一个有三个元素的数组*/
	int (*p2)[3];//声明1个(注意是1个!)int类型的指针且这个指针指向一个有且必须有3个元素的数组

	int *p3;

	//int (*p2)[4];//当执行p2=&arr时会报错,因为arr为三个元素,p2指向的是一个四个元素的地址
	
	//p1 =arr;//会报错。p1为指针数组第一个元素的地址,是指针的指针。arr为数组第一个元素的地址,是一个指针,不能赋值

	/*想要p1分别指向arr三个元素中的一个,可采用如下方法,注意p1中的每个元素都是一个指针*/
	p1[0] = &arr[0];
	p1[1] = &arr[1];
	*(p1+2) = &(*(arr+2));//与p1[2] = &arr[2]等效,上篇已经说过

	cout<<&arr[0]<<": "<<arr[0]<<endl;
	cout<<p1[0]<<": "<<*p1[0]<<endl;

	cout<<&arr[1]<<": "<<arr[1]<<endl;
	cout<<p1[1]<<": "<<*p1[1]<<endl;

	cout<<&arr[2]<<": "<<arr[2]<<endl;
	cout<<p1[2]<<": "<<*p1[2]<<endl;
	cout<<"============================"<<endl;

	p2 = &arr;//p2是一个指向具有三个元素的数组的指针,也就是说p2是arr指针的指针
	//对p2取值是一个指针,*p2+i为arr中第i个元素的指针
	cout<<*p2<<": "<<**p2<<endl;//cout<<*p2+0<<": "<<*(*p2+0)<<endl;
	cout<<*p2+1<<": "<<*(*p2+1)<<endl;
	cout<<*p2+2<<": "<<*(*p2+2)<<endl;
	cout<<"============================"<<endl;
	
	p3 = arr;//将arr首地址赋给p3
	/******************************************************************
	下面若干行代码说明数组首地址和数组地址之间的区别,虽然它们的值相同,
	但是占用的空间不同,数组首地址占用一个元素的空间,数组地址占用的却是
	整个数组的空间,这点对比下面+1代码可以看出
	******************************************************************/
	cout<<arr<<endl;//数组首地址
	cout<<p1[0]<<endl;//数组首地址	
	cout<<*p2<<endl;//数组首地址
	cout<<p3<<endl;//数组首地址
	cout<<"============================"<<endl;

	cout<<arr+1<<endl;//数组首地址+1
	cout<<p1[0]+1<<endl;//数组首地址+1
	cout<<*p2+1<<endl;//数组首地址+1
	cout<<p3+1<<endl;//数组首地址+1
	cout<<"============================"<<endl;

	cout<<&arr<<endl;//取数组的地址,数组用首地址表示数组的地址
	cout<<p2<<endl;//取数组的地址
	cout<<"============================"<<endl;

	cout<<&arr+1<<endl;//数组的地址+1
	cout<<p2+1<<endl;//数组的地址+1
	cout<<"============================"<<endl;

	/*下面两行代码为了说明一个恒等式p2[i][j]=*((*p2+i)+j)*/
	cout<<*p2+2<<": "<<*(*p2+2)<<endl;
	cout<<&p2[0][2]<<": "<<p2[0][2]<<endl;
	return 0;
}

总结:
(1)数组用首元素的地址作为数组的地址,虽然值相同,但是占用的空间大小不同。数组地址表示的是整个数组的空间大小。
(2)*p[3]是声明了包含三个指针元素的数组;(*p)[3]声明了一个指针,指向了一个具有三个元素(注意是三个)的数组。
(3)恒等式p[i][j] = *((*p+i)+j)

猜你喜欢

转载自blog.csdn.net/zhuyinglong2010/article/details/44261933