ok, 既然有了这样一个结论,我们就可以 写出来很多挺有意思的程序了。 比方说,我们以前对数组的控制都是 用数组名加下标的这种方式来进行的,其实啊 你还可以有其他的方式,比方说看这个程序, 在这个程序里头我定义了一个数组a 5,仍然付出式值10,11,12,13,14; 定义了一个指针变量p,付出数值NULL, 先打印a,毫无疑问我会打印出来数组的地址, 然后把a付给p,再去打印p,这也毫无疑问, 还会打印数值地址。然后接下来呢我打印 *p, 先不去看结果,我们就能够推论出来 *p 应该打印谁呀, 因为a,a, 数组名是指向数组的第一个元素的指针,所以当你把这个数组, 把a付给p以后,p也指向了数组的第一个元素, 所以,当你打印 *p 的时候,实际上就相当于 你去打印数组的第一个元素,也就是在这个地方,实际上你要打印谁呀, a 0, 对不对? ok,然后呢,打印完这个a 0 以后, 接下来去打印 *p++, 那么看到这个 *p++,我们首先要考虑的一个问题是什么啊? 运算符优先级,两个运算符在这里,我们应该先听谁的呀, 谁的优先级高啊,是不是++运算的优先级高啊? 所以说,对于这个表达式而言,我们一定要先听从++运算的, 先听++运算的指挥,然后呢再去进行新运算。 那么如果上面打印是 a 0 的话, 那么应该打印出什么来呢?在这个地方?它是会打印 a 0 呢, 还是会打印出 a 1 呢? 应该会打印a o。 那有的人会说为什么呀?你不是先要进行++,然后在取这个 * 嘛 所以说当然应该打印a 1 咯,no, 你忘记了,加加运算的含义是说先使用前面的变量, 然后再进行加加。 虽然它具有比较高的等级,它是我们的大领导, 大领导发话了,你先去做,做完了之后你在加加, 听从了这一个命令以后,我们在去做这个 * 的运算, 做完 * 的运算之后再来加加,所以说这个地方会打印出a 0 的值,同时呢,p指向了谁呀? 指向了a 1, 那么在底下在进行一次新p ++运算,那么会打印出什么来? 先打印出a1 的值,然后在对p进行加加运算,所以打印完了之后, p应该指向a 2,p应该指向a 2。ok,我们来看这个程序的运行结果。 首先呢打印出数组的地址,也就是数组的起始地址,也就是数组的首元素的地址。 然后呢把它付给p又打印一遍,这两个肯定是一样的,毫无疑问。 然后呢,我就打印 *p, 因为数组名是指向数组第一个元素的地址,所以打印 *p的时候,应该 打印数组第一个元素的值,也就是10,先把它打印出来, 后然呢打印 * p ++, 因为++运算的含义是说先去使用这个P,然后再进行++,所以说会先打印出10, 在打印完这个10以后呢,指针会从这里移到这里, 然后呢再去打印* p ++,这个时候呢, 先去打印* p 的值,也就是a1的值,先打印11, 然后在去加加,加加运算之后,指针指向这里, 这就是整个程序的运行结果,当打印完最后一个11以后, 指针指向了数组的第三个元素。 ok, 通过这个程序我们就可以看得出来,当我们遇到一个数组的时候, 除了我们可以用原来的这种用数组名和下标结合起来去访问数组元素的这种方式以外, 我们还可以利用指针变量去访问一个数组, 于是我们可以得出这样的结论来。 如果你定义了一个数组 int a 10,然后呢你又定义了一个指针变量, 当然这个指针变量是int型元素的, 其实通过这个,通过指针的基类型,我们也可以看的出来,这个指针其实只能指向数组的一个元素, 如果有这样的定义的话,我就可以进行这样的赋值,Pointer=a, 这一句赋值其实就等价于 pointer=& a (0) 这是我们讲过的。 那么当赋完这样的值之后,那么数组的访问啊, 就可以不再去使用a i 的这种方式了,当然你仍然可以用, 不过你又多了一种方式,你用 pointer + i 的这种方式, 比方说 pointer + i 其实就等价于 a+ i, 因为a是首元素的地址,对不对? 那这个地址跟 i 进行相加,其实就等于第i 个元素的地址,所以说p+ i, 就等价于第i 个元素的地址。 我们前面刚刚讲过, 对于一个指针变量进行加加的操作,它的含义是说, 跨过这个指针变量所指向的那片区域, 所以说如果是加 i 的话,刚好相当于是第i 个元素的地址, 那么在这个基础上,我们就可以看的出来,如果我们去写 *pointer + i 的话, 是不是这个东西就完全等价于 * a+i, 于是它也完全等价于 a (i) 这是我们想要的一个结论。也就是说如果我们使用一个指针变量来访问一个数组的话, 原来的 a i 都可以写成 * pointer + i, 这种方式。其实除了这种方式之外啊, 你甚至可以直接对pointer使用下标运算符, 写出这样一个东西来 pointer (i),其实这个也是允许的。 写这个东西,就相当于上面我们刚刚讲过的 *(pointer +i), 所以当我们定义完这样一个东西之后,其实它, 它和它,这三者的含义是等价的, 你可以使用它们中的任何一个来获取数组中第i 个元素的值。 比方说啊, 原来的一个对数组访问的程序,我们就可以完全用指针来重写一下。 比放说对这一个程序,这两个程序完成了相同的功能, 在左边的这个程序里头,我们仍然用原来的方法定义了一个数组, 然后呢,用一个for循环,通过cin,a(i)的这种方式对每个元素进行赋值, 同时呢,我们用cout, a(i)的这种方式把每个元素都打印出来, 那么如果你使用了指针的话,你就可以直接写成这样子了啦, 定义完数组之后呢,定义一个指针变量,并且呢把a 付给它, 那么通过这样一个程序呢,指针就指向了数组的第一个元素, 然后呢我就可以使用这样的一个程序 cin 点 *p++,通过这种方式, 对数组中的元素进行逐一的赋值。 然后呢,我还可以用一个办法,就是说用一个for 循环, 通过 *p - - 这种方式去逆序的去打印这个数组, 所以原始的这个程序就完全的被转化成了这样一个程序。 当然这个程序只是一个展示,那么 未来呀,我们会在其他的程序里头给大家展示这样做有什么好处。 不过啊,在这我们需要强调一点, 要使用这种方式来对数组进行操作,有一点 必须一定要注意,什么意思呢, 当我们啊使用一个指针来指向数组的第一个元素的时候, 无论把数组名和第一个元素的地址付给它都可以, 我们特别需要注意, a++ 是没有任何意义的,为什么呢? 因为a不是一个变量,它是一个常量。 这是我们已经知道的,但是p++就有意义, 因为p是一个普通的指针变量, 所以说我们可以对p进行++,- - 的操作,这是没有问题的, 同时呢,因为p是一个指针,所以说 p其实没有,p其实可以指向任意的一个存储区域, 包括它可以指向数组最后一个元素以后 的元素。 其实以前的也可以,就是说p完全 可以指向一个数组元素以外的一片区域, 它是有这个能力的,这个p是有这个能力的。 所以说当我们使用指针来操作数组的时候,一定一定要注意, 指针加减操作时一定要注意有效的范围。 也就是说这个指针实际上市非常灵活的一个东西, 它完全可能跑出数组的那个范围。 如果你超出了数组在内存中的存储区域, 那么对p的任何操作,其实就是没有意义的。而且是 危险的。所以说,你一定要注意有效的范围。 其实呢,从这个意义上,这也是指针的一个缺点, 它的安全性不太好。这是指针的一个缺点。比方说对于这样一个程序, 定义一个a5数组,然后呢,我们让一个 iPtr指向这样一个数组的第二个元素, 可以吗? 完全可以。能让iPtr指向数组的第一个元素我们就可以让iPtr直接指向数组的第二个元素。没什么不可以。 然后接下来我们做一个iPtr减减,做iPtr减减以后, iPtr就指向了a0.这个时候如果我们对新iPtr进行一个操作,没有问题, 实际上就相当于把a0赋成3了,但是如果接下来继续 进行减减,这个时候就要特别小心因为它就指向了 数组第一个元素之前的又一个元素。 这个就非常非常的危险,因为谁知道 那片空间里面保存的是什么东西啊?而且呢在很多 编译环境之下进行这样的一个操作,编译器不会报任何错误出来。 这个时候如果我们再对新iPtr做一个赋值的话,那就有可能会对内存造成损害。 所以说阿,这是我们特别需要注意的一件事情。好,那说到这儿阿, 用指针指向一维数组的相关的知识,我们就已经介绍的差不多了。 接下来呢,我们看两个小例子。第一个例子, 那么在这个例子中呢,我首先定义了一个数组 a5,然后呢定义了一个指针p, 让它呢指向数组中的元素a3,然后呢我对新p 进行重新赋值,赋值成100。赋完值以后呢,我来打印几个数。 比方首先我去打印*p加加,那当然在这个地方会打印出100,打印完之后呢, 那指针p呢,执行加加的操作。于是呢,指针p指向了数组的最后一个元素。 然后再去打印*p减减,这个时候呢,会首先先把这个5打印出来。 然后呢,执行减减的操作,于是指针又指向了 这个元素,a3这个元素。 那么指向a3这个元素之后呢,再去执行*减减p, 因为减减p和*的优先级是相同的,所以 说呢这个表达式执行的时候会先去执行减减p,然后再去执行新的运算, 所以说呢,首先指针会移到这个位置。 然后呢,再去执行新的运算,最后打印出3来。 执行的一个结果。我们再看一个例子。 这个例子的作用阿,是利用两个指针对数组中的元素啊,进行一个倒置的操作。 倒置的一个操作。我们来看一下这个程序。 定义一个数组a时,两个指针p和q, 那么初始值呢都是now. 然后利用指针变量p从键盘上读入 10个数,给数组a10赋值。赋完值以后呢, 再用一个循环,但注意这个循环中,p等于a,也就是说p指针指向了数组的头, q呢等于a加9,也就是说,q指向了数组的结尾。 如果p小于q的话, 就是说如果指针q仍然处于指针p的右边, 那么就执行把*p和*q的值进行一个 互换。那么通过这种方式我们就实现了把一个数组的元素 原来从正序调整为逆序。比方说这个程序的执行结果就是这样的。 输入1,2,3,4,5,6,7,8,9,0 那么输出的结果呢0,9,8,7,6,5,4,3,2,1。 是这样的一个结果。OK,那么说到这儿呢,我们基本上 把指向一维数组的指针跟大家介绍了一下。 那么大家在写程序的过程中呢,可以锻炼着使用指针来完成一些数组的任务。 OK,那么这次课呢我们就先讲到这, 下次课呢我们将介绍指向多维数组的 指针。OK,好,谢谢大家。