试论【数组指针】与【指针数组】

一、【数组指针】

     数组指针是指向数组的一个指针,说的有点废话的感觉。例如:int (*p) [4]; 表示指向4个元素的数组指针,数组中每一个元素都为整型。

     注意,这里的(*p)的括号不能去掉,p其实是包含4个元素的一维数组,p指向该一维数组的首地址

P→

(*p)[0](*p)[1](*p)[2](*p)[3]
  数组指针的示意图

如果有如下语句:

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

p=a;

那么,在上面示意图中,(*p)[0]、(*p)[1]、(*p)[2]、(*p)[3]分别保存4个元素1、2、3、4的地址。p+1表示将指针位置移动到下一行,p、p+1和p+2分别表示指向二维数组的第一行、第二行和第三行。

p→1234
p+1→5678
p+2→9101112

*(p+2)+3表示数组a的第2行第3列的元素地址,也就是&a[2][3]的值,即是12。

实例应用:

#include <stdio.h>
void main()
{
	int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
	int (*p)[4];    //数组指针变量声明
    int row,col;
	 p=a;           //指针p指向数组元素为4的数组
	 /*打印输出数组指针p指向的数组的值*/
	for(row=0;row<3;row++)
	{
		for(col=0;col<4;col++)
		{
			printf("a[%d,%d]=%-4d",row,col,*(*(p+row)+col));
		}
		printf("\n");
	}
	/*通过改变指针p修改数组a的行地址,改变col的值修改数组a的列地址*/
    for(p=a,row=0;p<a+3;p++,row++)
	{
		for(col=0;col<4;col++)
		{
			printf("(*p[%d])[%d]=%p",row,col,((*p)+col));
		}
		printf("\n");
	}
}

 

二、【指针数组】
 

      1、 指针数组是一个数组,数组中的元素是指针类型的数据。(表明指针数组中的每一个元素都是一个指针变量)

指针数组的定义:int *p[4];

注意一点:[]运算符优先级比*高,(1)p与[]优先结合,形成p[]数组形式;(2)p[]然后与*运算符相结合,表示此数组是指针类型的。每个数组元素是一个指向整型的变量。

换一句话说:指针数组首先是一个数组,其次它说保存的是指针类型的变量。注意啦:保存的变量是 指针类型

       2、指针数组的作用

指针数组常常用于存储一些长度不同的字符串数据,你想一想,如果你将那些长短不一的字符串存在多维数组里面,就会导致部分空间不能利用,造成内存资源浪费。因为多维数组采用的是由最长的数组决定分配内存单元的。而采用指针数组保存字符串,则是自动根据字符串内容长度来分配内存单元的。

实例应用:

#include <stdio.h>
void main()
{
	/*指针数组的定义*/
	char *book[4]={"C Programming language","Assembly Language","Java Language","Natural Language"};
	int n=4;
	int row;
	char *arrayPtr;
	/*方法一:通过数组名输出*/
	printf("方法一:通过数组名输出:\n");
	for(row=0;row<n;row++)
	{
		printf("第%d个字符串:%s\n",row+1,book[row]);
	}
	/*方法二:通过指向数组的指针输出*/

	printf("方法二:通过指向数组的指针输出:\n");
	for(arrayPtr=book[0],row=0;row<n;arrayPtr=book[row])
	{
		printf("第%d个字符串:%s\n",row+1,arrayPtr);
		row++;
	}
}
 

 三、综合探讨

       区别指针数组和数组指针两个概念:

       (1)数组指针首先是一个指针,并且它是一个指向数组的指针;指针数组首先是一个数组,并且是用来保存指针变量的数组(数组指针是指针,指针数组是数组)

       (2)数组指针(也称行指针
        定义: int (*p)[n];

        元素表示:(*a)[i]  
        分析:()优先级高,首先说明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][]

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

        (3)指针数组

         定义: int *p[n]; 

         元素表示:*a[i]   *(a[i])是一样的,因为[]优先级高于*
         分析:[]优先级高,先与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]。所以要分别赋值。
       (4)用来指向二维数组时,其引用和用数组名引用都是一样的。

                比如要表示数组中i行j列一个元素:*(p[i]+j) == *(*(p+i)+j) == (*(p+i))[j] == p[i][j]

       (5)注意:在实际应用中,对于指针数组,我们经常这样使用:

             typedef int* pInt;

             pInt a[4];

        (6)实例,小试牛刀:

#include <stdio.h>
int main()
{
	int c[4]={1,2,3,4};
	int *a[4];  //定义指针数组 
	int (*b)[4];//定义数组指针
	b=&c;
	for(int i=0;i<4;i++)
	{
		a[i]=&c[i];
	}
	//输出结果
	printf("*a[1]=%d\n",*a[1]);
	printf("(*b)[2]=%d\n",(*b)[2]);
	return 0;
}

       注意1:定义了数组指针,该指针指向这个数组的首地址必须给指针指定一个地址(给予初始值地址,容易犯的错得就是,不给b地址,直接用(*b)[i]=c[i]给数组b中元素赋值,这时数组指针不知道指向哪里,调试时可能没错,但运行时肯定出现问题。

       注意2:使用指针时要注意这个问题。但为什么a就不用给他地址呢,a的元素是指针,实际上for循环内已经给数组a中元素指定地址了。但若在for循环内写*a[i]=c[i],这同样会出问题。

 

                                                                                               简而言之:定义了指针一定要知道指针指向哪里

 

**************************************************************************************************************************************************************************************

❤永葆一颗纯洁、宽容平和、仁慈谦卑和意气风发的心!

态度决定一切     努力改变命运

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值