二维数组与指针全面理解

指向二维数组的指针学习笔记
2018-03-12 13:59:50 aFakeProgramer 阅读数 1169更多
分类专栏: c语言基础知识
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/usstmiracle/article/details/79525951
二维数组与一维数组的关系
二维数组的指针指向一维数组的指针
一维数组的情况下:数组名代表数组首地址*(a+i)=a[i]
二维数组与指针

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

说明:
二维数组的行指针指向一维数组 a,a+1,a+2 行指针的移动单位是以数组为单位进行移动
列指针指向数组的元素a[0]、a[1]、a[2]列指针的移动单位是以数组元素为单位进行移动
A:二维数组是一个特殊的一维数组。
B:对于int a[3][4]而言3表示二维数组中有三个一维数组,每个一维数组里面又含有4个元素。
C:定义了一个一维数组为a,它里面含有三个元素a[0]a[1]a[2],而每个元素,又是一个含有4个元素的一维数组
D:对于一维数组,a[i]就代表一个数
对于二维数组而言,a[i]本身还是一个数组,a[i]是数组名
所以a[i]它依然是一个地址(指针)
E:对于二维数组里面a,a+1,a+i而言,a+i是指向a[i]的而a[i]它本身也是一个数组,所以a+i是指向一维数组的指针
也被称为行指针,而且行指针的移动单位是以数组为单位进行移动
F:对于二维数组里面的a[i]而言,a[i]是指向元素a[i][0],换句话说,a[i]是指向一维数组元素的指针(列指针),而且列指针是以元素为单位来移动的
G:二维数组中的列指针a[i]这个指针可以越界
H:二维数组中的a,a+1,a+2 虽然是行指针,但是他们都是常量,不能自加,为了让行指针能够实现移动,就要定义一个行指针变量。所以需要定义一个指向一维数组指针变量。
I:以后只能把a,a+1…a+i的值赋给该指针,因为它们都是行指针
k:如果把指向一维数组的指针,赋给二维数组的数组名,那么这个指针,就可以当成二维数组来使用
int a[3][4],(p)[4]=a;
a[i][j]=p[i][j]=
((a+i)+j))=(*(p+i)+j))
格式:
int (*p)[数组长度];
int (*p)[4]; 定义了一个指针为p 这个指针,是一个行指针,那么以后这个指针只能够指向一个一维整型数组的,
并且它所指向的一维整型数组,里面要含有4个元素

int a[3][4]
a–> a[0]—>a[0][0] **a=*a[0]=a[0][0]
a[0][1]
a[0][2]
a[0][3]
a移动一个是移动了一行,是指向一维数组的指针
a[0]是指向一维数组元素的指针(列指针,移动一个元素)
a+1–> a[1]—>a[1][0] **(a+1)=*a[1]=a[1][0]
a[1][1]
a[1][2]
a[1][3]

a+2–> a[2]—>a[2][0]
a[2][1]
a[2][2]
a[2][3]

*a=a[0]
*a[0]=a[0][0]
**a=a[0][0]

**(a+1)=a[1]=a[1][0]
((a+1)+2)=
(a[1]+2)=a[1][2]

((a+i)+j)=*(a[i]+j)=a[i][j] //这个结论很重要

例子:

main()//这里的每一个main()函数都是一个单独的例子
{

int a[3][4]={{1,2,0,1},{1,1,0,2},{3,2,0,1}},k1,k2,k3;
k1=**a***a+1;                   //**a=a[0][0]=1 *  1+1=   2
k2=**a**(*a+**a+1);             //1* *(*a+1+1)=*(a[0]+2)=a[0][2]=0
k3=**a*(*(*a+*(*(a+1)+2)));     //*(*(a+1)+2)=a[1][2]=0     **a*(*(*a+0))=1*1=1
    printf("k1=%d,k2=%d,k3=%d",k1,k2,k3);			

}

	main()//这里的每一个main()函数都是一个单独的例子
	{
	
		int a[3][4]={{1,2,0,1},{1,1,0,2},{3,2,0,1}},k1,k2,k3;
		k1=**a***a+1;                   //**a=a[0][0]=1 *  1+1=   2
		k2=**a**(*a+**a+1);             //1* *(*a+1+1)=*(a[0]+2)=a[0][2]=0
		k3=**a*(*(*a+*(*(a+1)+2)));     //*(*(a+1)+2)=a[1][2]=0     **a*(*(*a+0))=1*1=1
		
		k4=*a[2];//a[2][0]=3
		k5=(*a)[2]//a[0][2]
		k6=*(a[0]+6)//a[1][2]
		二维数组中的a[i]这个指针可以越界(非常重要)
                   printf("k1=%d,k2=%d,k3=%d",k1,k2,k3);			

	}

数组名是常量,不能自加

int a[3][4],*p[4];

定义了一个指针为p 这个指针,是一个行指针,那么以后这个指针只能够指向一个一维整型数组的,
并且它所指向的一维整型数组,里面要含有4个元素
p=a[0];//这是错的
p=a//p 是行指针 a,a+1…a+i

以后只能把a,a+1…a+i的值赋给该指针,因为它们都是行指针,行指针是以数组为单位进行移动的

main()
{

	int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}},*p[4],k1;
	p=a+1;
	k1=**p+*(*p+1)+*(*(p+1)+1)//a[1][0]+a[1][1]+a[2][1]=21
	 printf("k1=%d",k1);
}


main()//这里的每一个main()函数都是一个单独的例子
{
	
	int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}},(*p1)[4]=a,*p2=a[1],k;
	k=*(*p1+1)**p2;     //*(a[0]+1) *  a[1][0]=a[0][1]*a[1][0]=2*5=10
        printf("k1=%d",k1);
}		
	
	main()
	{
	
		int a[3][3]={{2},{4},{6}},i,*p=&a[0][0];//这边的p是列指针
		for(i=0;i<2;i++)
		{
			if(i==0)
			{
				a[i][i+1]=*p+1;
			}
			else
			{
				++p;
				
			}
			printf("%d",*p);
		}
			
	}        key //23
	
	
		
	main()//这里的每一个main()函数都是一个单独的例子
	{
	
		int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
		int (*p)[4]=a,i,j,k=0;
		for(i=0;i<3;i++)
		{
			for(j=0;j<2;j++)
			{
				k+=*(*(p+i)+j);//k+=p[i][j];
			}
			printf("k=%d",k);//把前两列加起来33
		}
	}

如果把指向一维数组的指针,赋给二维数组的数组名,那么这个指针,就可以当成二维数组来使用

int a[3][4],(p)[4]=a;
a[i][j]=p[i][j]=
((a+i)+j))=(*(p+i)+j))
main()
{
int a[][3]={{1,2,3},{4,5,0}},(*pa)[3],i;
pa=a;
for(i=0;i<3;i++)
{
if(i<2)
pa[1][i]=pa[1][i]-1;
else pa[1][i]=1;
}
printf("%d",a[0][1]a[1][1]+a[1][2]);//7
}

指向一维数组的指针,一般会与二维数组配合使用,实际上就是对二维数组进行编程,
实际就是以二维数组作为函数参数。
A:型参用数组,实参也用数组
函数定义 : fun(int a[][4])
函数调用: fun(a)
B:型参用指针,而实参用数组:
函数定义: fun(int (*p)[4])
函数调用: fun(a)
C:型参用指针,而实参用指针:
函数定义: fun(int (*p)[4])
函数调用: fun(指针a)

//编写一个函数,目的是为了求出二维数组中所有元素的和

int sum(int (*p)[4])
{
int s,i,j;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
s+=p[i][j];
}
}
return s;
}
int sum(int a[][4])
{
int s,i,j;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
s+=a[i][j];
}
}
return s;
}

main()
{
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
printf(“sum=%d”,sum(a));
}
例子:
把二维数组的第一行元素与最后一行的元素调换,把第二行与倒数第二行的元素调换,以此类推

1 2 3 4 17 18 19 20
5 6 7 8 13 14 15 16
9 10 11 12 转换成 9 10 11 12
13 14 15 16 5 6 7 8
17 18 19 20 1 2 3 4

a[i][0] > a[j][0]
a[i][1] > a[j][1]
a[i][2] > a[j][2]
a[i][3] > a[j][3]

第0行与第4行的元素交换

void funhuan(int (*p)[4])
{
int i,j,n,t;
for(i=0,j=4;i<j;i++,j–)//实现行的互换
{
for(n=0;n<4;n++)//每行的4个元素
{
t=p[i][n];
p[i][n]=p[j][n];
p[j][n]=t;
}
}
}

main()
{
int a[5][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int i,j;
for(i=0;i<5;i++)
{
for(j=0;j<4;j++)
{
printf("%5d",a[i][j]);
}
printf("\n");
}
printf("\n");
funhuan(a);
for(i=0;i<5;i++)
{
for(j=0;j<4;j++)
{
printf("%5d",a[i][j]);
}
printf("\n");
}
}

编写一个程序,它的功能是把一个二维数组中周边元素都置为零

void setZero(int (p)[4])
{
int i,j;
for(i=0;i<4;i++)
{
p[0][i]=0;//
(*(a)+i)=0;
p[3][i]=0;
p[i][0]=0;
p[i][3]=0;
}
}
main()
{
int a[5][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
setZero(a);
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
printf("%5d",a[i][j]);
}
printf("\n");
}

给一个一维数组,中所有行的元素的值都向右移m个位置,左边置零。

void move0(int *a,int n)
{
for(int i=0;i<n;i++)
{
a[n-i]=a[n-i-1];
}
a[0]=0;
}

main()
{
  int a[4]={1,2,3,4},i,m;
	
	for(i=0;i<4;i++)
   {
	   printf("%5d",a[i]);
	}	
		printf("\n");
		scanf("%d",&m);
	for(i=0;i<m;i++)
	{
		move0(a,4);
	}		
	for(i=0;i<4;i++)
   {
	   printf("%5d",a[i]);
   }
}

编写一个函数,把N*N的一个二维数组,根据给定的M值将这个二维数组中所有行的元素的值都向右移m个位置,左边置零。
1 2 3 4 0 0 1 2
5 6 7 8 5 6 7 8
9 10 11 12 转换成 9 10 11 12
13 14 15 16 13 14 15 16

若m=1

为了方便思考,假设先移动一行,移动第i行

先看第一行, 1 下标为2开始移
,2 下标为1开始移
3 下标为0开始移
i 下标为3-i开始移

m=2时
a[i][3]=a[i][1]
a[i][2]=a[i][0]
下标隔2, 因为m=2
j=3-m//从该位置开始移
for(j=3-m;j>=0;j–)
{
a[i][j+m]=a[i][j];//右移m个位置
}
for(j=0;j<m;j++)//左边置零
{
a[i][j]=0;
}

程序实现:

void fun(int (*a)[4],int m)//m右移多少位
{
int i,j;
//每一行都要移位,假设先移第i行
for(i=0;i<4;i++)
{
for(j=3-m;j>=0;j–)//表示在移动
{
a[i][m+j]=a[i][j];
}
for(j=0;j<m;j++)//把前面剩下的元素设为0
{
a[i][j]=0;
}
}
}

main()
{
int a[5][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},m;
printf(“输入一个整数给m:”);
scanf("%d",&m);
fun(a,m);
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)//表示在移动
{
printf("%5d",a[i][j]);
}
printf("\n");
}

//编写一个函数,可以求出二维数组每一行的最大值,并存放在数组num里面返回
void fun(int (*a)[4],int *num)
{
int i,j,max,k=0;
for(i=0;i<4;i++)
{
max=a[i][0];
for(j=1;j<4;j++)
{
if(max<a[i][j])
max=a[i][j];
}
num[k++]=max;
printf("\n");
}
}
main()
{
int a[4][4]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},num[4]={0};

	for(i=0;i<4;i++)
{
	for(j=0;j<4;j++)
	{
		printf("%5d",a[i][j]);
	}
	printf("\n");
}
fun(a,num);
	for(i=0;i<4;i++)
{
	
		printf("%5d",num[i]);
	
	printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值