C语言基础学习笔记(11):指针与数组的关系

C语言基础学习笔记(11):指针与数组的关系

图: 北英格兰,惠特比港(Whitby Harbour)

Guderian出品

指针与一维数组的关系

一维数组在内存中是线性排列的。假设存在一个任意的int类型数组a[N],数组名a代表了数组的首地址&a[0],则&a[i]等价于(a+i)。注意这里a+1不是加上1个字节,而是取决于a的基类型(这里是int,即为4个字节):a+1等价于a+sizeof(基类型)。因此我们可以得出一维数组元素的等价引用形式:a[i]等价于*(a+i)。下面举两个例子:

示例一

用指针读入一维数组并用指针输出一维数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main()
{
int a[10], i, *p = NULL;
p = a;

for (i=0; i<10; i++)
scanf("%d", &p[i]);

p = a;
for (i=0; i<10; i++)
printf("%d", p[i]);
printf("\n");

return 0;
}

示例二

示例一的另一种实现方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

int main()
{
int a[10], *p = NULL;

for (p=a; p<a+10; p++)
scanf("%d", p);

for (p=a; p<a+10; p++)
printf("%d", *p);
printf("\n");

return 0;
}

指针与二维数组的关系

兄弟们,做好心理准备,下面的内容对萌新不友好

内存中数据的存储形式都是线性的,二维数组在内存中按行线性存储,但可以用两种方式看待它。

第一种方式:行是列的索引

a[2][3]为例,它的存储结构如图:

想要访问某一行某一列的元素,需要先访问某一行,再访问某一列:首先定义类型为int [3]的行指针int (*p)[3](不要写成*p[3],否则就成了有三个元素的指针数组)用于存储a[2][3]的行指针,只需这么做:p = a或者p = &a[0]

这里要正确理解a&a[0]的含义,一种较为简单的理解方式是:首先把a看做一个一维数组a[2],有两个int [3]型元素,那么其首地址就是a或者&a[0];然后再把a[2]看成一个一维数组a[2][3],那么其首地址就是a[0]或者*aa&a[0]的含义就是第0行的行指针,*aa[0]&a[0][0]的含义就是第0行第0列的指针(后面在第二种方式会讲到)。

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main()
{
int a[2][3] = {1,2,3,4,5,6};
int (*p)[3];
p = a;
for(int i=0; i<2; i++)
for(int j=0; j<3; j++)
printf("%d ", *(*(p+i)+j));
return 0;
}

输出结果为:

1
1 2 3 4 5 6

第二种方式:Only one dimension in RAM!

这种方式模拟了数组在内存上存储的真实情况,把a[2][3]看做一维数组,先按行分块,每一块再按列排序,要访问一个元素只需计算它内存地址的偏移量即可。定义int *p;并令p = &a[0][0](或*aa[0]),那么要访问a[i][j]只需等价于访问*(p+i*2+j)

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main()
{
int a[2][3] = {1,2,3,4,5,6};
int *p;
p = *a;
for(int i=0; i<2; i++)
for(int j=0; j<3; j++)
printf("%d ", *(p+i*2+j));
return 0;
}

输出结果为:

1
1 2 3 4 5 6

【更多C语言系列】

本文标题:C语言基础学习笔记(11):指针与数组的关系

文章作者:G-SS-Hacker

发布时间:2020年02月22日 - 14:21:43

最后更新:2020年02月22日 - 14:30:30

原始链接:https://G-SS-Hacker.github.io/C语言基础学习笔记(11):指针与数组的关系/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。