数组指针 指针数组

1、数组指针(指向数组的指针)

(1)数组在内存中的表示

创建一个数组就是在内存里面开辟一块连续的空间,比如int a[4];就是在内存里面开辟了一个大小为4*sizeof(int)字节的内存空间。二维数组是特殊的一维数组。

先来看一段代码:

<strong><span style="font-size:16px;">void main()
{
	int a[2][2]={1,2,3,4};//这是一个2*2的二维数组
    int (*p)[2];//数组指针
    p=a;//令p指向数组a
}</span></strong>

注意到代码中这句话:int (*p)[2];这里的p是一个数组指针变量。

a中各个元素在内存中是这样存放的:

 

(2)理解数组名和数组指针变量

OK,现在我们思考a,a[0],a[1],p,a+1,a[0]+1,p+1到底是什么,思考3秒钟:

分析:

a是一个数组名,类型是指向一维数组的指针,不是变量,a的值是指针常量,即不能有a++或者a=p这些操作。a指向这块连续空间的首地址,是&a[0][0]。

a[0]是一维数组名,类型是指向整型的指针,是&a[0][0],这个值是一个常量。

a[1]是一维数组名,类型是指向整型的指针,是&a[1][0],这个值是一个常量。

p是一个数组指针变量,指向一维数组的指针变量是&a[0][0]。可以执行p++;p=a等操作。

a+1表示指向下一行元素,也可以理解为指向下一个一维数组。

*(a+1)是取出第一行的首地址。

a[0]+1是指向第0行第1个元素,也可以理解为指向一维数组a[0]的第一个元素。

p+1同a+1

*(p+1)同*(a+1)

虽然a跟a[0]值是一样,但类型不一样,表示的意义不一样。通过分析就不难理解为什么*(*(a+i)+j)和a[i][j]等效了。

 

(3)指针是数组的迭代器

<span style="font-size:16px;">#include<stdio.h>
#define M 2
#define N 3

int main()
{
	int a[M][N]={1,2,3,4,5,6};
	int *start=&a[0][0];
	int * const end=start+M*N;
	for(;start!=end;start++)
		printf("%-5d",*start);
	putchar('\n');
	return 0;
}</span>

理解这段代码,用指针遍历一个二维数组,是不是很像C++标准库里面vector的迭代器。注意这里只用了一个for循环,这也可以说明二维数组其实就是特殊的一维数组。

 

(4)数组名与数组指针变量的区别

 

从(2)中的分析中得出数组名是指针,类型是指向元素类型的指针,但值是指针常量,声明数组时编译器会为声明所指定的元素数量保留内存空间。数组指针是指向数组的指针,声明指针变量时编译器只为指针本身保留内存空间。

 

看看这个代码:

<strong><span style="font-size:16px;">#include<stdio.h>
void main()
{
	int a[2][2]={1,2,3,4};//这是一个2*2的二维数组
    int (*p)[2];//数组指针
    p=a;//令p指向数组a
	printf("%d\n%d\n",sizeof a,sizeof p);
}</span></strong>

猜一猜输出是什么?


困惑了吗?为什么结果会是这样的呢,让我们先初步了解一下sizeof关键字吧,下面是MSDN上sizeof的说明:

 



注意到说明中的红色字体,当sizeof用于变量时返回这个变量占用的实际空间的大小。当sizeof用于数组名时,返回整个数组的大小(这里的大小指占用的字节数)。p是一个指针变量,这个变量占用四个字节。而a是数组名,所以sizeof a返回数组a中的全部元素占用的字节数。

 了解了sizeof,猜猜下面这段代码输出什么

<span style="font-size:16px;"><strong>#include<stdio.h>

void main()
{
	int a[2][2]={1,2,3,4};//这是一个2*2的二维数组
    int (*p)[2];//数组指针
    p=a;//令p指向数组a
    printf("%d\n%d\n",sizeof(a+1),sizeof(p+1));
    printf("%d\n%d\n",sizeof(a+0),sizeof(p+0));
}</strong></span>

运行结果:

从结果中看出,a在做+运算时是转化成了指针变量,此时a+i的类型是一个指针变量,而不是一个数组名。但a[i]是一个一维数组的数组名,sizeof(a[0])的值是8

 

现在再来看一段代码:

<strong><span style="font-size:16px;">#include<stdio.h>

void f(int a[][2])
{
	printf("%d\n",sizeof a);
}
void main()
{
	int a[2][2]={1,2,3,4};//这是一个2*2的二维数组
	printf("%d\n",sizeof a);
	f(a);
}</span></strong>

再猜一下输出是什么?

是不是又有点困惑呢?

解释:这是因为传参的时候数组名转化成指针变量,注意到函数f中f(int a[][2])这里并不需要指定二维数组的长度,此处可以改为int (*a)[2]。所以传过来的就是一个数组指针变量。这样明白了吧!

 

总结:数组名的类型是指向元素类型的指针,值是指针常量。(a+1)的类型是一个指针变量。把数组名作为参数传递的时候实际上传递的是一个指针变量。sizeof对变量和数组名操作时返回的结果会不一样。数组指针是指向数组的指针,其值可以是变量。

2、指针数组(存放指针的数组)

(1)认识指针数组

一个存放int类型的数组称为整型数组,那么存放指针的数组就叫指针数组。

<strong><span style="font-size:16px;">#include<stdio.h>

void main()
{
	int i=1,j=2;
	//p先跟[]结合,然后再跟*结合
    int *p[2];//指针数组,存放指针的数组
	p[0]=&i;
	p[1]=&j;
	printf("%d",sizeof(p));
}</span></strong>

断点调试分析:

 

此例数组p就两个元素,p[0]是指向i的指针,p[1]是指向j的指针。这两个指针都是int型指针,所以p是存放int型指针的数组。sizeof(p)返回数组占用的总空间,所以程序输出是8

 

(2)指针数组用法举例

来自《the c programming language》的一个例子,对字符串进行排序,看了下面这个例子,相信你就体会到了指针数组的好处了。

 

 

 3、深入思考

数组名a、a[0]、a[1],数组指针p到底在内存中是怎么存储的呢?存放在内存中的哪里呢?是在代码段吗?求解惑!

 

 4、参考资料

《c和指针》 《the c programming language》 等

源地址:http://blog.csdn.net/touch_2011/article/details/6966980

另外的一篇文章

数组指针(也称行指针)
定义 int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
 p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针。

指针数组
定义 int *p[n];
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1是错误的,这样赋值也是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。

这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

 

优先级:()>[]>*


源地址:http://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值