有关二维数组的指针问题

建立在以下资料上的思考
http://c.biancheng.net/view/2022.html

二维数组的指针问题

[二维数组]在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例:

int a[3][4] = { {0, 1, 2, 3}, {10, 11, 12, 13}, {20, 21, 22, 23} };

在概念上存储的过程:

0123
10111213
20212223

在内存中存储的过程:

01231011121320212223

C语言允许把一个二维数组分解成多个一维数组来处理。

​ 对于数组 a,它可以分解成三个一维数组,即a[0]、a[1]、a[2]

每一个一维数组又包含了 4 个元素。

a[0] 包含a[0][0]、a[0][1]、a[0][2]、a[0][3]

假设数组 a 中第 0 个元素的地址为 1000,那么每个一维数组的首地址如下图所示:
在这里插入图片描述

(数组 a 为 int 类型,每个元素占用 4 个字节)

二维数组的地址

a=a[0][0]=a[0] 
a+1=a[1] 
a[0]+1=a[0][1]

1.指针:数据类型 (*指针变量名)[N]

指向由m个元素构成的一维数组的指针变量

这种指针使得p+1不是指向a[0][1],而是指向a[1],p的增值以一维度数组的长度为单位,这种指针称为行指针

int (*p)[4] = a;

括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4]

1.1 p指向数组 a 的开头,也即第 0 行p+1前进一行,指向第 1 行

​ 对指针进行加法(减法)运算时,它前进(后退)的步长与它指向的数据类型有关,p 指向的数据类型是int [4],那么p+1就前进 4×4 = 16 个字节,p-1就后退 16 个字节,这正好是数组 a 所包含的每个一维数组的长度。也就是说,p+1会使得指针指向二维数组的下一行,p-1会使得指针指向数组的上一行。

1.2 *(p+1)表示取地址上的数据,也就是整个第 1 行数据

​ 注意是一行数据,是多个数据,不是第 1 行中的第 0 个元素。

1.3 *(p+1)+1表示第 1 行第 1 个元素的地址

*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。

1.4 *(*(p+1)+1)表示第 1 行第 1 个元素的值

​ 增加一个 * 表示取地址上的数据。

通过上述推论,可以得到这个等式

a+i == p+i
a[i] == p[i] == *(a+i) == *(p+i)  
a[i][j] == p[i][j] == *(a[i]+j) == *(p[i]+j) == *(*(a+i)+j) == *(*(p+i)+j)第i行第j列的值

2.指针:数据类型 *(指针变量名) = 数组名[N]

指向数组中的首元素地址。

int *p=a[0];

括号中的*表明 p 是一个指针,它指向数组中首元素的地址,一个int类型的数据元素。

2.1 *p=a[i]指向数组第i行第0个数据

*p=a[1]会使得指针指向二维数组的第一行首元素,*p=a[2]会使得指针指向数组的第二行首元素。p在这里存储的是第i行首元素。

2.2 *(p+1)表示取下一位地址上的数据,也就是第0行第1个数据

​ 对指针进行加法(减法)运算时,它前进(后退)的步长与它指向的数据类型有关,p 指向的数据类型是int,那么p+1就前进 4个字节,p-1就后退 4 个字节。*(p+1)相当于a[0][1]。在二维数组当中,数据在内存地址上存储是连续排列的。*(p+i)相当于前进4*i个字节取从*p往后数第i位元素的地址。例如 *(p+6)取得的数据为a[1][2]的值12

通过上述推论,可以得到这个等式

a[i][j] == p[j] == *(p+j)

小结

​ 在二维数组当中,aa[0]都表示二维数组中首元素地址。

a是二维数组的名字,指向所属元素首元素,其中每一个元素为一个行数组,因此指针的移动单位为“行”

a[0]是一维数组的名字,指向所属元素首元素,其中每一个元素为一个int类型的数据,因此指针的移动单位为“列(单个数据元素)”

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值