从而呢满足,如果我们写*p的话,他就可以把二维数组中每一个元素的值给打印出来。
OK!这是这个空。这个空填上了,但是这个事情我并没有讲完。你看,在这个程序中,
通过这个赋值啊,实际上我们是让p指向了数组的第一个元素,
然后接下来呢,我们是一直对p进行++的运算。
直到++到12,也就是说a一共有12个元素嘛,
我就++到12。其实我们中间根本就没有考虑
什么第一个小数组,第二个小数组的问题,对不对? 但是我们也把这些数组的元素一个一个全都打印出来了。
那这是为什么呀?大家还记得我们在讲二维数组的存储方式的时候曾经用过这张图吗?
当我们把一个二维数组存放到内存里的时候,实际上我们是把这个二维数组给它拉成了
直线来存储的,对不对?我们会把二维数组中的
各个小元素在内存里面依次排开,排成一条线
这样来存储。数组呢,都会存储在一片连续的地址空间
里头,那么二维数组也一样。在这片连续的地址空间里头
就把二维数组的各个元素依次排开。所以说当我们使用这个程序不断地
通过对指向每一个元素的这么一个指针进行++的运算,
它就会不断地去指向下一个元素,下一个元素,下一个元素,下一个元素,
直到12个元素全部遍历完。
所以说啊,通过这种方式我们可以把二维数组中所有的元素全部都打印出来。
这其实是指向二维数组的指针非常常用的
一种方法,用指针来访问二维数组中的 元素。这是这个例子。
同学我们再来看一道题。
程序填空,并且呢,判断正误。
就是在这个题里头你既需要把这个空填起来,又需要判定这个红色的程序是对
还是错。那在这儿呢,我需要特别跟大家强调,这个题啊,非常的重要。
它不只是一道简单的例题,我们呢,需要从这个例题中啊,学习一些东西。
OK,我们来看一下这道题。 这道题完成了什么功能呢?完成一个非常简单的功能,从键盘上输入i,j,
然后呢,让你打印出一个二维数组中
a[i][j]的值。好,我们来看一下这道题。
首先我定义的是一个二维数组,a[3][4]。
然后呢,在这儿我给p赋值的时候啊,赋的是a。
在这个条件下,我希望你完成对p的定义。
OK,那如何去定义p呢?很显然,
如果我们能够把a赋给p的话,那就意味着 p和a的含义必须是相同的。
于是呢,我们就从这点上先来分析这个空,应该怎么去填。
也就是说这个p,应该如何去定义。我们先来分析一下,
那么要分析这样一个问题呀,我们就可以从 p等于a这句程序啊,开始分析。
那么既然我要根据p等于a这句程序写出p的定义,
那我就得分析一下什么是a。a呢
相当于指向a[3][4]的“第一个元素”的指针。
然后呢,所谓的这个“第一个元素”是一个 “包含了4个int型元素的一个一维数组”。
这些都是我们讲过的了。所以, a相当于一个“包含4个
int型元素的一维数组”的地址。
既然我们要把一个这样的地址赋给p, 所以我们就可以得出来,
如果要去定义一个p的话,p的那个基类型应该是什么呢?
还记得什么是基类型吧?比方说对于一个指向int型的变量,
指针变量p而言,那么它的基类型就是
int型。就是写在指针并列定义最前面的这个类型。
那么在这里,既然我们要把一个“包含4个int型元素的
一维数组”的这么一个地址给p的话,那p的基类型也只能是
“包含4个int型元素的一维数组”。
怎么去定义呢?你可以这样来定义。
变量的定义语句是这样来写的,括号*p[4]。
通过这种方式,你就定义了一个指针变量p。这个p呢,
它是指向一个具有4个int型元素的
这么一个一维数组的。这就是这个p的基本含义。
也就是说通过这样一个定义啊,你就得到这样一个p,它是指向一个
“包含4个int型元素的一维数组”。
那么说到这儿啊,那个空我们终于可以去完成了。所以呢回来我们先把这个空填上。
因为前面的Int已经写好了,所以说我们只需要在这儿填*p[4]就可以了。注意呢,括号不能够省略。
如果省略的话完全就是另外一个意思了。OK,那么在这儿呢,我们
就完成了变量p的定义。那么接下来呢,我们再来看一下变量的输出。
那么定义完之后呢,我们就可以把a啊赋给p了。把a赋给p之后呢,输入i和,
这是行号和列号。然后呢,我希望打印出来
a[i][j]。想把这个值打印出来。我是怎么写的呢?我是这样来写的。
*(*(p+i)+j) 这个式子正确吗?
其实关于这个式子的判别啊,那同学们啊,现在完全可以独立地去判别一下。
那么在这儿呢,我们一起来分析一下。*(*(p+i)+j)
到底表示什么含义呢?也就是说它是什么呢?
我们一步一步地来分析。先来分析p的含义。
刚刚定义过,p是指向一个“包含4个int型元素的一维数组”的。
既然它指向一个“包含4个int型元素的一维数组”,所以
p+i的含义就是第i+1个“包含4个int型元素的一维数组”的地址,
这是我们分析过很多遍的。由此呢我们就可以得到
一个结论,其实p+i就相当于&a[i]。
因为i从0开始嘛,所以说它是第i+1个一维小数组的名字,对不对?
也就是说a[i]呢,也就是代表着
指向了第i+1个小数组的第一个元素的指针,
对不对?于是&a[i]它的含义就是
指向“包含4个int型元素的一维数组”的
这个地址。也就是它的指针。
这是p+i的含义。那么接下来我们继续分析,
那么p+i的含义有了,那么*(p+i)的含义是什么呢? 那很明显了,*(p+i)就相当于a[i]。
那么有了这个之后呢,我们再去分析*(p+i)+j
的这个含义。如果再给它加上j的话,其实就像等于a[i]+j。
那有的同学问了,a[i]+j是什么含义啊?含义很明显啊。
因为a[i]是第i+1个小数组的第一个元素的指针,
对不对?所以a[i]+j就是
第i+1个小数组的第j个元素的指针。其实它就相当于 &a[i][j],是不是这意思啊?
完全相同。那么有了这个之后我们再去分析
整个的*(*(p+i)+j)的含义,那么整个的*(p+i)+j的含义就是啊,
相当于a[i][j]。其实它的含义就等价于a[i][j]。
那么所以说我们在这儿写,*(*(p+i)+j) 这个是正确的。
其实啊,那么根据C语言的规范
*(*(p+i)+j)又可以直接把它写成p[i][j]。
这也是可以的。 也就是说整个这个程序,如果在这儿写p[i][j]的话,
也完全是成立的。那么从这个例子啊,我们就可以看出指针的很重要的一个用途,
那如果我定义一个这样的指针的话,我直接可以用这个指针来代替数组名来使用了。
所以说指针呢,具有非常强大的功能。那么我们在这儿呢,
只是列述了一些关于指针的一些基本的知识。
那么关于指针的使用呢,还需要大家在实际的程序里头啊,
不断地去磨练。OK,那关于指针 与多维数组的关系我们就先讲这么多。
那么在下一次课中呢,我们会介绍指针与函数的关系。 好,谢谢大家。
希望大家啊,听的明白,学的愉快。