最近在练习 C 语言计算机二级的程序设计题,碰到了二维数组和指针的结合,当时怎么调试都不对,自己也记不清楚该怎么用了就跑去看书翻资料重新复习。自己纠结的问题是二维数组 int a[3][4]的数组名是二级指针吗?答案不是,而在的复习讲解上说是地址的地址是错的(但是他的讲解确实很让人懂二维数组的使用),a 退化为指针后,类型为 int (*)[4], 该指针指向含 4 个 int 类型元素的一维数组。(例:一维数组 b [4],b 则退化为元素指针)既然 a 都不是指针的指针,则想通过 int **p=a 对 p 进行赋值就是不可实现的。
那么如何实现通过指针p来对a[3][4]来进行操作?
在看如何赋值之前有必要了解一下
这几个 &a,a,a[0],&a[0],&a[0][0] 地址 (因 a[0][0] 为元素值,不在讨论范围内) 的不同之处。
#include<stdio.h>
void main()
{
int a[3][4]={20,30,40,50,60,70,80,90,100,110,120,130},i,j;
printf("&a=%dn",&a);
printf("&a+1=%dn",&a+1);
printf("a=%dn",a);
printf("a+1=%dn",a+1);
printf("&a[0]=%dn",&a[0]);
printf("&a[0]+1%dn",&a[0]+1);
printf("a[0]=%dn",a[0]);
printf("a[0]+1=%dn",a[0]+1);
printf("&a[0][0]=%dn",&a[0][0]);
printf("&a[0][0]+1=%dn",&a[0][0]+1);
}
运行结果(该结果为本人电脑运行看,可能有所不同):
&a=5241364
&a+1=5241412
a=5241364
a+1=5241380
&a[0]=5241364
&a[0]+15241380
a[0]=5241364
a[0]+1=5241368
&a[0][0]=5241364
&a[0][0]+1=5241368
通过观察可以看出 &a,a,a[0],&a[0],&a[0][0] 的结果都是 5241364,证明他们的地址是相同的。
但是都进行 + 1 操作后就知道不同了。
&a+1 和 & a 差值为 48,正好是二维数组的长度(4(int 长度)X3X4=48),+1 是加了一个二维数组长度。
a+1 和 a 的差值为 16,是 a [][4] 的长度,进行 + 1 则从 a 退化为 a [0] 的地址进行加值之后变为 a [1] 的地址,可以证明 a 加 1 是从 a [0] 到 a [1] 的变化。
&a [0]+1 和 & a [0] 的差值为 16,&a [0] 表示一行 (一个一维数组) 的首地址,进行 + 1 后是下一组的首地址& a [1]。a [0]+1 和 a [0] 的差值为 4,a [0] 表示这一行的首元素的地址,+1 则是从 a [0] 开始退化为 a [0][0] 的指针之后进行加值则变为 a [0][1] 的地址;&a [0][0]+1 和 & a [0][0] 的差值为 4,&a [0][0] 表示这一行(一维数组)的首元素的值的地址,当 + 1 则变为 a [0][1] 的地址。
如果还是不了解看下图(搜集于网络图片)
分析图
由上面了解之后再看下面就方便理解了。
第一种方式:通过将定义 p 为:int (*p)[4] 形式,和上面 a 所退化为指针后的类型相同,因此则可以直接将 a 赋值给 p;代码如下:
#include<stdio.h>
void main()
{
int a[3][4]={20,30,40,50,60,70,80,90,100,110,120,130},i,j;
int (*p1)[4]=a;
for(i=0;i<3;i++)//数组形式(方便理解)
{
for(j=0;j<4;j++)
printf("%3d ",p1[i][j]);
printf("n");
}
printf("n");
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)//指针形式
printf("%3d ",*(*(p1+i)+j));
printf("n");
}
}
第二种方式:在内存中,并不存在多维数组,因为内存是一维的,内存里面不分行也不分列,元素都是按顺序一个一个往后排的,所以二维数组中的每一个元素在内存中的地址都是连续的。(摘自讲解中的话),因此我们只要找到令指针指向二维数组的首地址就能通过顺序来找到接下的元素。因为二维数组 a 的地址和 a [0] 是一样的,我们让 int *p=a[0],则可以找到首地址,调用过程中需要通过 *(p1+4*i+j) 来找接下来的元素。
#include<stdio.h>
void main()
{
int aa[3][4]={20,30,40,50,60,70,80,90,100,110,120,130},i,j;
int *p1=a[0];//[0]是地址
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)//
printf("%3d ",*(p1+4*i+j));
printf("n");
}
}
到此分析完毕。