《c语言教学资料》6指针_第1页
《c语言教学资料》6指针_第2页
《c语言教学资料》6指针_第3页
《c语言教学资料》6指针_第4页
《c语言教学资料》6指针_第5页
已阅读5页,还剩69页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第第6章章 指针指针2 第第6 6章章 指针指针本章内容本章内容 6.2 变量的指针和指针变量变量的指针和指针变量 6.3 指针运算指针运算 6.4 一维数组与指针一维数组与指针 6.1 地址与指针地址与指针 6.5 二维数组与指针二维数组与指针3第第6 6章章 指针指针本章内容本章内容 6.7 指针变量作函数的参数指针变量作函数的参数 6.8 函数与指针函数与指针 6.9 指向指针的指针变量指向指针的指针变量 6.6 字符数组与指针字符数组与指针 6.10 指针应用举例指针应用举例46.1 6.1 地址与指针地址与指针v内存就是计算机内部存储内存就是计算机内部存储器,是由存储单元组成的。器,

2、是由存储单元组成的。存储单元的编号就是存储单元的编号就是内存内存地址地址。 v在程序中定义一个变量,在程序中定义一个变量,在对程序进行编译时,系在对程序进行编译时,系统就会给这个变量分配具统就会给这个变量分配具体的内存单元。这个单元体的内存单元。这个单元有个地址,变量名和其地有个地址,变量名和其地址对应。址对应。 2000Ha556.1 6.1 地址与指针地址与指针v在程序中我们是通过变量名来对在程序中我们是通过变量名来对内存单元进行存取操作的。内存单元进行存取操作的。这种这种按变量名存取变量值的方式称为按变量名存取变量值的方式称为“直接访问直接访问”方式。方式。v例如:例如:a=5;a=5;

3、v b=a; b=a;v其实程序经过编译以后已经将变其实程序经过编译以后已经将变量名转换为变量的地址,对变量量名转换为变量的地址,对变量值的存取都是通过地址进行的。值的存取都是通过地址进行的。2000Ha5b52004H66.1 6.1 地址与指针地址与指针v还有一种还有一种 “间接访问间接访问” 变量值变量值的方法:将的方法:将a a变量的地址存放在另变量的地址存放在另一个专门存放地址的变量一个专门存放地址的变量papa中,中,通过通过papa变量存取变量存取a a变量的值。变量的值。v例如:变量例如:变量a a存放数值存放数值5;5; 变量变量papa存放存放a a变量的地址变量的地址20

4、00H2000H。vb=b=* *pa; pa; v什么是指针呢?什么是指针呢?变量的地址(编变量的地址(编号)就是变量的指针号)就是变量的指针。存放地址存放地址的变量就是指针变量。的变量就是指针变量。在这里的在这里的papa就是指针变量。就是指针变量。2000Ha5pa3020H 2000Hb576.1 6.1 地址与指针地址与指针v指针变量指针变量用来指向另一个变量。用来指向另一个变量。v为了表示指针变量和它所指向的变量之间的联系,为了表示指针变量和它所指向的变量之间的联系,在程序中用在程序中用“* *”符号表示指向(取指针内容),符号表示指向(取指针内容),它实际执行的是它实际执行的是“

5、间接访问间接访问”运算,如果已定义运算,如果已定义papa为指针变量且存放为指针变量且存放a a变量的地址,则变量的地址,则* *papa是是papa所所指向的变量。指向的变量。* *papa等价于等价于a a。v若若a a变量存放的值为变量存放的值为5 5,则,则a a代表代表5 5,papa代表代表a a的地址,的地址,* *papa代表代表a a,就是,就是5 5。8 6.2 6.2 变量的指针和指针变量变量的指针和指针变量本节内容本节内容 6.2.2 指针变量的引用指针变量的引用 6.2.1 指针变量的定义指针变量的定义96.2.1 6.2.1 指针变量的定义指针变量的定义v定义指针变

6、量的一般形式为定义指针变量的一般形式为 基类型基类型 * *指针变量名指针变量名; ;v下面都是合法的定义:下面都是合法的定义:vfloat float * *pfpf;vchar c,char c,* *pcpc;v可以用赋值语句使一个指针变量得到另一个变量可以用赋值语句使一个指针变量得到另一个变量的地址,从而使它指向该变量。例如:的地址,从而使它指向该变量。例如:vpc=&c;pc=&c; 将变量将变量c c的地址存放到的地址存放到pcpc中,因此中,因此pcpc就就“指向指向”了变量了变量c c。106.2.1 6.2.1 指针变量的定义指针变量的定义v在定义指针变量时要

7、注意两点:在定义指针变量时要注意两点: 在定义指针变量时,在定义指针变量时,指针变量名前面加指针变量名前面加“* *”表示该表示该变量的类型为指针型变量。变量的类型为指针型变量。 但但在使用指针变量时,在使用指针变量时,指针变量名前面加指针变量名前面加“* *”表示进表示进行间接寻址操作(取指针内容)。行间接寻址操作(取指针内容)。如有:如有: int i=3,j,int i=3,j,* *pi; pi; “* *”表示表示pipi的类型为指针型变量的类型为指针型变量 pi=&i;pi=&i; j=j=* *pi; pi; “* *”表示取指针表示取指针pipi所指变量的值所指

8、变量的值 结果:结果:j j的值为的值为3 3。 一个指针变量只能指向定义时指定的基类型的变量,一个指针变量只能指向定义时指定的基类型的变量,不能忽而指向一个整型变量,忽而指向一个实型变量。不能忽而指向一个整型变量,忽而指向一个实型变量。116.2.2 6.2.2 指针变量的引用指针变量的引用v指针变量同普通变量一样,在使用之前要先定义,指针变量同普通变量一样,在使用之前要先定义,但需注意的是指针变量定义后,变量值不确定,但需注意的是指针变量定义后,变量值不确定,应用前还必须先赋予具体的值。未经赋值的指针应用前还必须先赋予具体的值。未经赋值的指针变量是不能使用的。变量是不能使用的。v未经赋值的

9、指针变量叫做未经赋值的指针变量叫做“野指针野指针”,它的初始,它的初始值是随机的。如果未经赋值而对它随机指向的内值是随机的。如果未经赋值而对它随机指向的内存单元进行操作,可能产生存单元进行操作,可能产生严重后果严重后果。v指针变量只能赋予地址,绝不能赋予任何其他数指针变量只能赋予地址,绝不能赋予任何其他数据,否则将引起错误。据,否则将引起错误。126.2.2 6.2.2 指针变量的引用指针变量的引用v6.2.2.1 6.2.2.1 指针变量的初始化指针变量的初始化v指针变量初始化的一般形式为:指针变量初始化的一般形式为: 基类型基类型 * *指针名指针名= =初始地址值;初始地址值;v变量的地

10、址是由编译系统内部分配的,用户不知变量的地址是由编译系统内部分配的,用户不知道变量的具体地址,所以不能直接给出地址值,道变量的具体地址,所以不能直接给出地址值,只能通过运算获得。有两个有关指针的运算符:只能通过运算获得。有两个有关指针的运算符:v& &:取地址运算符:取地址运算符v* *:指针运算符:指针运算符( (取指针内容运算符取指针内容运算符) ) int a,int a,* *pa=&a; pa=&a; /用用& &取取a a的地址,的地址,papa指向指向a a变量变量 * *pa=10; pa=10; /给给papa所指向的变量(所指

11、向的变量(a a)赋值)赋值136.2.2 6.2.2 指针变量的引用指针变量的引用#include main()char x,y;char *p1,*p2;x=a; y=b;p1=&x;/把变量x的地址赋给p1p2=&y;/把变量y的地址赋给p2printf(%c, %cn,x,y);printf(%c, %cn,*p1,*p2);【例例6-1】通过指针变量访通过指针变量访问字符型变量。问字符型变量。146.2.2 6.2.2 指针变量的引用指针变量的引用v“&”&”和和“* *”是互逆运算(可以抵消):是互逆运算(可以抵消): & &* *p

12、1p1的含义是什么的含义是什么? ? 先进行先进行* *p1p1的运算,它就是变量的运算,它就是变量x x,再执行,再执行& &运算就是运算就是&x&x。因此,因此,& &* *p1p1与与&x&x等价,也与等价,也与p1p1等价等价,表示变量,表示变量x x的的地址地址。 * *&x&x的含义是什么的含义是什么? ? 先进行先进行&x&x运算,得运算,得x x的地址,再进行的地址,再进行* *运算,得到运算,得到&x&x所指所指向变量向变量x x。可见。可见* *&x&am

13、p;x和和* *p1p1以及变量以及变量x x是等价的是等价的,即,即 * *&x&x与与x x等价等价,表示变量,表示变量x x的的值值。 p2p2& &* *p1p1; 它的作用是将它的作用是将&x(x&x(x的地址的地址) )赋给赋给p2p2,与与p2=p1;p2=p1;等价等价。如。如果果p2p2原来指向原来指向y y,经过重新赋值后它已不再指向,经过重新赋值后它已不再指向y y了,而了,而指向了指向了x x。 156.2.2 6.2.2 指针变量的引用指针变量的引用v ( (* *p1)+p1)+v 相当于相当于x+x+。p1p1仍指向

14、仍指向x x。结果。结果x x的值加的值加1 1。X X的值变为的值变为bb。v * *p1+p1+,v 相当于相当于* *(p1+)(p1+)。v 由于由于+在在p1p1的右侧,是的右侧,是“后加后加”,因此首先对因此首先对p1p1的原值进行的原值进行* *运算,运算,得到得到x x的值。式子的取值的值。式子的取值为:为:aa。v 然后使然后使p1p1的值改变,这样的值改变,这样p1p1不再不再指向指向x x了,而是指向了了,而是指向了y y变量。变量。2000Hxap13020H 2000Hyb2001H166.2.2 6.2.2 指针变量的引用指针变量的引用是值是值值的几种形式值的几种形

15、式是地址是地址地址的几种形式地址的几种形式是赋值操作是赋值操作176.2.2 6.2.2 指针变量的引用指针变量的引用#include main() int *p1,*p2,*p,x,y; scanf(%d,%d,&x,&y); p1=&x;p2=&y; if(xy)p=p1;p1=p2;p2=p;printf(x=%d y=%dn,x,y);printf(min=%d max=%dn,*p1,*p2);【例例6-2】输输入入x和和y两个整两个整数,按从小到数,按从小到大的顺序输出大的顺序输出x和和y。186.2.2 6.2.2 指针变量的引用指针变量的引用pp

16、p1p1p2p2xxyy&x&x&y&y612126&x交换前交换前交换后交换后196.2.2 6.2.2 指针变量的引用指针变量的引用v6.2.2.2 6.2.2.2 指针变量的赋值指针变量的赋值vint xint x;vint int * *p p;v若需要通过指针变量若需要通过指针变量p p来操作来操作x x,那么可以先让,那么可以先让p p指指向向x x,这只要将,这只要将x x的地址赋予的地址赋予p p p=&x;p=&x;206.2.2 6.2.2 指针变量的引用指针变量的引用v在对指针变量赋值时,要注意以下问题:在对指针变量

17、赋值时,要注意以下问题:v在将一个普通变量的地址赋值给指针变量时,在将一个普通变量的地址赋值给指针变量时,普通变量必须先定义,再使用。例如:普通变量必须先定义,再使用。例如: int int * *p=&x; /xp=&x; /x变量还未定义变量还未定义v不能将一般的普通变量,例如整型变量赋给指不能将一般的普通变量,例如整型变量赋给指针变量,指针变量也不能赋给普通变量。例如:针变量,指针变量也不能赋给普通变量。例如: int x=3,y,int x=3,y,* *p;p; p=x;p=x; /错误错误 p=&y; /p=&y; /可以可以 x=p; /x=p;

18、/错误错误216.2.2 6.2.2 指针变量的引用指针变量的引用v可以将一个指针的值赋给另一个指针变量;可以将一个指针的值赋给另一个指针变量; int x=3,y,int x=3,y,* *p1p1,* *p2;p2; p1=&x; p1=&x; p2=p1; /p2=p1; /可以可以v可以为一个指针赋值为可以为一个指针赋值为NULLNULL。 int int * *p=NULL;p=NULL;避免避免因为误因为误引用引用没有没有被初始化被初始化的指针变量的指针变量造成的严造成的严重问题。重问题。22 6.3 6.3 指针运算指针运算本节内容本节内容 6.3.2 指针的逻辑

19、运算指针的逻辑运算 6.3.1 指针的算数运算指针的算数运算236.3.1 6.3.1 指针的算数运算指针的算数运算v指针除了可以参与赋值和间接访问之外,只能进指针除了可以参与赋值和间接访问之外,只能进行加减运算和比较运算。在这些运算中,基类型行加减运算和比较运算。在这些运算中,基类型起着决定性的作用。起着决定性的作用。 v6.3.1.1 6.3.1.1 自加和自减运算自加和自减运算v指针变量可以进行自加和自减运算。指针变量可以进行自加和自减运算。 float xfloat x,* *p p; p=&xp=&x;v假定变量假定变量x x的内存起始地址为的内存起始地址为20002

20、000,进行如下运算:,进行如下运算: p+p+; 运算后运算后p p的值并不是的值并不是20012001,而是,而是20042004。因为基类型的数。因为基类型的数据占四个字节。据占四个字节。246.3.1 6.3.1 指针的算数运算指针的算数运算v6.3.1.2 6.3.1.2 与自加和自减相关的运算与自加和自减相关的运算 float xfloat x,y y,* *p p; p=&xp=&x; 假定假定x x,y y在内存中连续存储,且在内存中连续存储,且x x的内存起始地址为的内存起始地址为20002000,借此我们讨论几种常见的指针运算。,借此我们讨论几种常见的指针运

21、算。v* *p+p+和和* *(p+)(p+) 由于由于+运算与运算与* *运算优先级别相同,但结合次序都是由运算优先级别相同,但结合次序都是由右至左,故这二个表达式具有相同含义。又因为表达式右至左,故这二个表达式具有相同含义。又因为表达式p+p+的值为的值为p p加加1 1运算之前的值,因此,运算之前的值,因此,此表达式等同于此表达式等同于变量变量x x。不过,在计算完此表达是后,。不过,在计算完此表达是后,p p加加1 1,指向,指向y y。256.3.1 6.3.1 指针的算数运算指针的算数运算v* *+p+p和和* *(+p)(+p) 这是两个完全等同的表达式。因为表达式这是两个完全等

22、同的表达式。因为表达式+p+p的值为的值为p p加加1 1运算后的值,等于运算后的值,等于&y&y,指向,指向y y,因此,因此表达式等同于变量表达式等同于变量y y。v( (* *p)+p)+ 由于变量由于变量* *p p与变量与变量x x等价,此等价,此表达式相当于表达式相当于x+x+。v+(+(* *p)p) 此此表达式与表达式与+x+x等价等价,表达式计算后,表达式计算后,p p的值不变。的值不变。266.3.1 6.3.1 指针的算数运算指针的算数运算v6.3.1.3 6.3.1.3 加减算术运算加减算术运算v指针只可以与指针和整数进行部分加减算术运算。指针只可以与指

23、针和整数进行部分加减算术运算。 指针与整数的加减法指针与整数的加减法 指针可以与整数进行加减法运算,结果仍是指针。指针可以与整数进行加减法运算,结果仍是指针。 p=p+1p=p+1; p+p+; 两者作用相同,相当于指针移过一个两者作用相同,相当于指针移过一个由基类型所定义的位移量。由基类型所定义的位移量。 整数与指针的加减法整数与指针的加减法 一个整数与指针的加法结果仍是指针,但整数不能与指一个整数与指针的加法结果仍是指针,但整数不能与指针进行减法运算,即类似针进行减法运算,即类似5-p5-p形式的表达式是错误的。形式的表达式是错误的。 指针与指针的加减法指针与指针的加减法 两个指针不能进行

24、加法运算,结果没有意义。两个指针两个指针不能进行加法运算,结果没有意义。两个指针的减法是允许的,但结果不再是指针而是一个整数,表的减法是允许的,但结果不再是指针而是一个整数,表示两个地址之间的距离。示两个地址之间的距离。276.3.2 6.3.2 指针的逻辑运算指针的逻辑运算v指针的逻辑运算相对简单,可以使用关系运算符指针的逻辑运算相对简单,可以使用关系运算符比较两个指针的大小,但通常是在两个指针指向比较两个指针的大小,但通常是在两个指针指向同一目标,如一个数组或一内存块时才使用。同一目标,如一个数组或一内存块时才使用。v可以将一个指针与可以将一个指针与0 0或或NULLNULL进行比较,以测

25、试该指进行比较,以测试该指针是否已指向某一确定的内存地址。针是否已指向某一确定的内存地址。28 6.4 6.4 一维数组与指针一维数组与指针本节内容本节内容 6.4.2 指向数组的指针变量的运算指向数组的指针变量的运算 6.4.1 通过指针引用一维数组元素通过指针引用一维数组元素296.4 6.4 一维数组与指针一维数组与指针1 1200020003 35 520042004 20082008a0a0 a1a1 a2a2= =20002000a a数组代表类型相同、连续存放数组代表类型相同、连续存放连续连续数组名代表地址数组名代表地址地址地址数组名代表常量数组名代表常量常量常量306.4.1

26、6.4.1 通过指针引用一维数组元素通过指针引用一维数组元素v可以定义一个指向数组元素的指针变量,其方法可以定义一个指向数组元素的指针变量,其方法与以前介绍的定义指针变量的方法相同。例如:与以前介绍的定义指针变量的方法相同。例如:vint a3,int a3,* *p p;v因为数组因为数组a a为为intint型,所以指向该数组元素的指针型,所以指向该数组元素的指针变量也应该为变量也应该为intint型的指针变量。下面两种对指针型的指针变量。下面两种对指针变量赋值的方法是一样的:变量赋值的方法是一样的:vp=&a0; p=&a0; 或或 p=ap=a;v表示把表示把a0a0元

27、素的地址赋给指针变量元素的地址赋给指针变量p p。或者说。或者说p p指向指向a a数组的第数组的第0 0号元素。号元素。316.4.1 6.4.1 通过指针引用一维数组元素通过指针引用一维数组元素vp p,a a,&a0&a0都指向同一单元,它们都是数组都指向同一单元,它们都是数组a a的首的首地址,也就是数组地址,也就是数组a a的的0 0号元素号元素a0a0的首地址。但需的首地址。但需要注意的是:要注意的是:p p是变量,而是变量,而a a和和&a0&a0都是常量都是常量,所,所以不能进行以不能进行a+a+或或+a+a之类的操作。之类的操作。v如果指针变量

28、如果指针变量p p已指向数组中的一个元素,则已指向数组中的一个元素,则p+1p+1指指向同一个数组中的下一个元素。向同一个数组中的下一个元素。v如果如果p p的初值为的初值为a a,则,则p+ip+i和和a+ia+i就是就是aiai的地址,即的地址,即它们是指向它们是指向a a数组的第数组的第i+1i+1个元素。个元素。v* *(p+i)(p+i)和和* *(a+i)(a+i)就是就是p+ip+i或或a+ia+i所指向的数组元素:所指向的数组元素:aiai。326.4.1 6.4.1 通过指针引用一维数组元素通过指针引用一维数组元素v指向数组的指针变量也可以带下指向数组的指针变量也可以带下标:

29、标:pipi与与* *(p+i)(p+i)等价,就是等价,就是aiai。v所以数组元素的引用可以有以下所以数组元素的引用可以有以下两种表示方法:两种表示方法: 下标法,即用下标法,即用aiai或或pipi形式访形式访问数组元素问数组元素 指针法,即采用指针法,即采用* *(a+i)(a+i)或或* *(p+i)(p+i)形式,用间接访问的方法来访问数形式,用间接访问的方法来访问数组元素,其中组元素,其中a a是数组名,是数组名,p p是指向是指向数组的指针变量,其初始值数组的指针变量,其初始值p=ap=a。int a10,i,*p=a;循环输入10个数for(i=0;i10;i+)以下四种循环

30、体效果相同printf(“%3d”,ai);printf(“%3d”,pi);printf(“%3d”,*(a+i);printf(“%3d”,*(p+i);336.4.1 6.4.1 通过指针引用一维数组元素通过指针引用一维数组元素for (i = 0; i 3; i+)for (i = 0; i 3; i+)1 1200020003 35 52 20 01 1a a20042004 20082008 printf(%dn,printf(%dn, aiai);); * *(a+i)(a+i)= =20002000数组恒等式:数组恒等式:aiai * *(a+i)(a+i)346.4.1 6.

31、4.1 通过指针引用一维数组元素通过指针引用一维数组元素for (i = 0; i 3; i+)for (i = 0; i 3; i+)1 1200020003 35 52 20 01 1a a20042004 20082008printf(%dnprintf(%dn= =20002000p pp = a;p = a;, ai);, ai);, , pipi););* *(p+i)(p+i)356.4.1 6.4.1 通过指针引用一维数组元素通过指针引用一维数组元素1 1200020003 35 52 20 01 1a a20042004 20082008printf(%d n,printf(

32、%d n, p0p0););= =20002000p pp = a + 1;p = a + 1;printf(%d n,printf(%d n, * *(p+0)(p+0););printf(%d,%d n,printf(%d,%d n, p1p1, , p-1p-1););366.4.1 6.4.1 通过指针引用一维数组元素通过指针引用一维数组元素a0a0a1a1a2a2a a&a0, a&a0, a&a2, a+2&a2, a+2地址地址a0, a0, * *a, a, * *(a+0)(a+0)a2, a2, * *(a+2)(a+2)数值数值200020

33、00 20042004 20082008376.4.1 6.4.1 通过指针引用一维数组元素通过指针引用一维数组元素v与地址运算有关的总结:与地址运算有关的总结:v如果:如果:int i,x=5,int i,x=5,* *px=&x,a3=0,1,2,px=&x,a3=0,1,2,* *p=a;p=a;v那么:那么:x x、* *pxpx、aiai、* *a a、* *(a+i)(a+i)、* *p p、* *(p+i)(p+i)、pipi是值是值。为叙述方便不妨称其为。为叙述方便不妨称其为“0 0级地址级地址”。v而:而:&x&x、pxpx、&ai&a

34、mp;ai、a a、a+ia+i、p p、p+ip+i是地址是地址。为。为叙述方便不妨称其为叙述方便不妨称其为“一级地址一级地址”。v结论结论1 1:& &(取地址运算符)能使地址(取地址运算符)能使地址升级升级。v结论结论2 2:* *(取指针内容运算符)能使地址(取指针内容运算符)能使地址降级降级。v结论结论3 3:(下标运算符)能使地址(下标运算符)能使地址降级降级。v结论结论4 4:一维数组名是一级地址。(以后可类推到:一维数组名是一级地址。(以后可类推到多维数组)多维数组)386.4.2 6.4.2 指向数组的指针变量的运算指向数组的指针变量的运算v6.4.2.1 6

35、.4.2.1 指向数组的指针变量的自加和自减指向数组的指针变量的自加和自减 int a10int a10,* *p p; p=ap=a;v进行如下运算:进行如下运算: p+p+;v则指向数组的指针变量则指向数组的指针变量p p指向了移过一个指向了移过一个intint类型类型所定义的位移量,即所定义的位移量,即p p指向变量指向变量a1a1的地址。我们的地址。我们可以得出这样一个结论:可以得出这样一个结论:指向数组的指针变量进指向数组的指针变量进行的自加运算等同于使指针变量指向数组的下一行的自加运算等同于使指针变量指向数组的下一个数组元素。个数组元素。同样适用于同样适用于+p+p,p-p-和和-

36、p-p。 396.4.2 6.4.2 指向数组的指针变量的运算指向数组的指针变量的运算v6.4.2.2 6.4.2.2 指向数组的指针变量的加减算术运算指向数组的指针变量的加减算术运算 指向数组的指针变量与整数进行加减运算时,相当于指向数组的指针变量与整数进行加减运算时,相当于进行若干个自加或者自减运算,结果为指针变量指向相进行若干个自加或者自减运算,结果为指针变量指向相应的数组元素。应的数组元素。 一个整数与指向数组的指针变量相加的结果和前边讨一个整数与指向数组的指针变量相加的结果和前边讨论的指向数组的指针变量与整数相加效果一样,但是整论的指向数组的指针变量与整数相加效果一样,但是整数不能与

37、指针进行减法运算。数不能与指针进行减法运算。 两个指向同一数组的指针变量可以进行相减,但结果两个指向同一数组的指针变量可以进行相减,但结果是一个整数,为两个数组元素之间的距离(即两个地址是一个整数,为两个数组元素之间的距离(即两个地址之间的距离之间的距离, ,注意这个结果是以指针的基类型为单位注意这个结果是以指针的基类型为单位的)。的)。40数组与指针数组与指针v输出数组输出数组a9a9中的全部元素中的全部元素#include void main() int a9=1,2,3,4,5,6,7,8,9; int *p=a,i; for (i=0; i9; i+) printf(%4d ,*(a+

38、i); printf(n); for (i=0; i9; i+) printf(%4d , *p+); printf(n);41 6.5 6.5 二维数组与指针二维数组与指针本节内容本节内容 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素 6.5.3 指针数组指针数组 6.5.1 二维数组元素的地址二维数组元素的地址426.5.1 6.5.1 二维数组元素的地址二维数组元素的地址v我们定义二维数组:我们定义二维数组:int b24int b24;vb b是二维数组名,是一个地址常量,是数组第一行是二维数组名,是一个地址常量,是数组第一行的首地址。的首地址。b b、b+1b+1、b

39、+2b+2是指向各行的指针,不妨是指向各行的指针,不妨看成看成“二级指针二级指针”(通常的叫法是:(通常的叫法是:行指针行指针),),它们指向了各行的首地址。它们指向了各行的首地址。 v可以认为可以认为b0b0、b1b1、b2b2 是是b b的各个元素,用的各个元素,用指针表示,就是指针表示,就是* *b b、* *(b+1)(b+1)、* *(b+2)(b+2);只不过这;只不过这些些“元素元素”都是一维数组。既然它们都是一维数都是一维数组。既然它们都是一维数组名,不妨看成组名,不妨看成“一级指针一级指针”(通常的叫法是:(通常的叫法是:列指针列指针),它们指向了各行的第一列。),它们指向了

40、各行的第一列。436.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素v指针指针b b、b0b0和和* *b b都是指针且都指向数组的首地址,都是指针且都指向数组的首地址,但它们的基类型不同:但它们的基类型不同:v因为因为b b的的“元素元素”为一维数组,它的基类型是一为一维数组,它的基类型是一维数组,故维数组,故b b是指向一维数组的指针而不是指向整是指向一维数组的指针而不是指向整数的指针。由于一维数组名也是指针,故数的指针。由于一维数组名也是指针,故b b本质上本质上是一种指向指针的指针(不妨称为二级指针)。是一种指向指针的指针(不妨称为二级指针)。vb0b0是利用数组

41、是利用数组b b的下标引用得到的变量,的下标引用得到的变量,* *b b是是指针指针b b间接引用得到的变量,间接引用得到的变量,b0b0和和* *b b都是都是b b的第的第一个元素,都表示第一行的一维数组名,此刻它一个元素,都表示第一行的一维数组名,此刻它的元素为的元素为intint类型,故类型,故b0b0和和* *b b是指向是指向intint类型的类型的指针(不妨称为一级指针)。指针(不妨称为一级指针)。446.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素vint b24int b24,* *p p;vp=bp=b;v语句语句“p=b”p=b”表示把二维数组中表

42、示把二维数组中b00b00元素的地元素的地址赋给指针变量址赋给指针变量p p。p p指向数组指向数组b b的第一行第的第一行第0 0号元号元素,即第一个元素。素,即第一个元素。v对于二维数组中第对于二维数组中第i+1i+1行第行第j+1j+1列的元素即列的元素即bijbij我们可以看作是我们可以看作是b b数组中数组中“元素元素”bibi的的j j号元素,号元素,bibi是一个一维数组,可以看作是一个指针,指是一个一维数组,可以看作是一个指针,指向一维数组向一维数组bi0bi0的首地址,则元素的首地址,则元素bijbij的的地址为地址为bi+jbi+j,其基类型为,其基类型为intint类型;

43、类型;v再看数组再看数组b b,其,其“元素元素”bibi的地址为的地址为b+i,b+i,但其基但其基类型为一维数组类型。类型为一维数组类型。456.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素v如果将二维数组名如果将二维数组名a a看成一个行地址看成一个行地址(第(第0 0行的地址),行的地址),则则a+ia+i代表二维数代表二维数组组a a的第的第i i行的地址,行的地址,aiai可看成一个可看成一个列地址,即第列地址,即第i i行第行第0 0列的地址。列的地址。 行地址行地址a a每次加每次加1 1,表示指向下一行,表示指向下一行 列地址列地址aiai每次加每次加

44、1 1,表示指向下一列,表示指向下一列466.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素476.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素v对二维数组对二维数组 int a34int a34,有有 a-a-二维数组的首二维数组的首地址地址,即第,即第0 0行的首行的首地址地址 a+i-a+i-第第i i行的首行的首地址地址 ai ai * *(a+i)(a+i)-第第i i行第行第0 0列的元素列的元素地址地址 ai+j ai+j * *(a+i)+j(a+i)+j - -第第i i行第行第j j列的元素列的元素地址地址 * *(ai+j)

45、(ai+j) * *( (* *(a+i)+j) (a+i)+j) aij aij -第第i i行第行第j j列元素列元素的的值值486.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素va+i=&ai=ai=a+i=&ai=ai=* *(a+i)=&ai0,(a+i)=&ai0, 它们的地址它们的地址值相等,值相等,但是但是含义含义(级别)(级别)不同不同。 a+i a+i &ai, &ai,表示第表示第i i行首地址,指向行行首地址,指向行(二级二级)。)。 ai ai * *(a+i) (a+i) &ai0 &a

46、mp;ai0,表示第表示第i i行第行第0 0列元素地列元素地址,指向列址,指向列(一级一级)。)。496.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素二维数组两次取值是数值,二维数组两次取值是数值,其余情况是地址。其余情况是地址。*a或或a“* *”与数组名紧密相连,与数组名紧密相连,表示第表示第0行。行。 *a“* *”等价于等价于“ ”“ ”,都表,都表示取值。示取值。( (地址级别降一级地址级别降一级) )在一次取值之前加行在一次取值之前加行(a+i),一次取值之后加列一次取值之后加列(*a+j)。判断二维判断二维数组地址数组地址与值四项与值四项基本原则基本原则

47、506.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素&a23, &a23, * *(a+2)+3, a2+3(a+2)+3, a2+3 地址地址&a20,&a20, a+2, a+2, * *(a+2), (a+2), * *(a+2)+0, (a+2)+0, a2, a2+0a2, a2+0地址地址&a03, &a03, * *a+3, a+3, * *(a+0)+3, a0+3(a+0)+3, a0+3 地址地址&a00,&a00, a, a+0, a, a+0, * *a, a, * *(a+0),(

48、a+0),* *a+0, a+0, * *(a+0)+0, a0, a0+0(a+0)+0, a0, a0+0地址地址0行行0列列2行行0列列0行行3列列2行行3列列请指出各地址的级别!516.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素a23, a23, * *( (* *(a+2)+3), (a+2)+3), * *(a2+3)(a2+3) 数值数值a20,a20, * * *(a+2), (a+2), * *( (* *(a+2)+0), (a+2)+0), * *a2, a2, * *(a2+0)(a2+0)数值数值a03,a03, * *( (* *a+3),

49、 a+3), * *( (* *(a+0)+3), (a+0)+3), * *(a0+3)(a0+3)数值数值a00,a00, * * *a, a, * *( (* *a+0), a+0), * * *(a+0),(a+0),* *( (* *(a+0)+0), (a+0)+0), * *a0, a0, * *(a0+0)(a0+0)数值数值0行行0列列2行行0列列0行行3列列2行行3列列526.5.2 6.5.2 通过指针引用二维数组元素通过指针引用二维数组元素v输出数组输出数组a33a33中的全部元素中的全部元素#include void main() int a33= 1,2,3,4,5

50、,6,7,8,9; int *p; for(p=a0; pa0+9; p+)/当作一维数组当作一维数组 if(p-a0)%3=0) printf(n);printf(%4d,*p); 536.5.3 6.5.3 指针数组指针数组v一个数组,若其元素均为指针类型数据,称为指一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都针数组,也就是说,指针数组中的每一个元素都相当于一个指针变量。一维指针数组的定义形式相当于一个指针变量。一维指针数组的定义形式为为 类型名类型名 * *数组名数组名 数组长度数组长度 ; 例如:例如:int int * *p4p4;v由于由于

51、比比* *优先级高,因此优先级高,因此p p先与先与44结合,形成结合,形成p4p4形式,这显然是数组形式,它有形式,这显然是数组形式,它有 4 4个元素。个元素。然后再与然后再与p p前面的前面的“* *”结合,结合,“* *”表示此数组是表示此数组是指针类型的,每个数组元素指针类型的,每个数组元素( (相当于一个指针变量相当于一个指针变量) )都可指向一个整型变量。都可指向一个整型变量。546.5.3 6.5.3 指针数组指针数组v为什么要用到指针数组呢为什么要用到指针数组呢? ?这是因为它比较适合于这是因为它比较适合于用来指向若干个字符串,使字符串处理更加方便用来指向若干个字符串,使字符

52、串处理更加方便灵活。灵活。 v可以分别定义一些字符串,然后用指针数组中的可以分别定义一些字符串,然后用指针数组中的元素分别指向各字符串。如果想对字符串排序,元素分别指向各字符串。如果想对字符串排序,不必改动字符串的位置,只需改动指针数组中各不必改动字符串的位置,只需改动指针数组中各元素的指向元素的指向( (即改变各元素的值,这些值是各字符即改变各元素的值,这些值是各字符串的首地址串的首地址) )。这样,各字符串的长度可以不同,。这样,各字符串的长度可以不同,而且移动指针变量的值而且移动指针变量的值( (地址地址) )要比移动字符串所要比移动字符串所花的时间少得多。花的时间少得多。556.5.3

53、 6.5.3 指针数组指针数组v指针数组指针数组v数组元素为指针,数组元素为指针,用于处理二维数组或多个字符串用于处理二维数组或多个字符串数据类型数据类型 * *数组名数组名 数组长度数组长度 ;char *a4=Fortran,Lisp,Basic,NULLL i s p 0F o r t r a n 0B a s i c 0a0a1a2a3056数组与指针数组与指针v例例6.56.5:将:将5 5个英文人名按字母顺序排列后输出个英文人名按字母顺序排列后输出#include #include void sort(char *name,int n) char *p; int i,j,k; fo

54、r(i=0;in-1;i+)/比较法排序比较法排序 k=i; for(j=i+1;j0) k=j; if(k!=i)/只进行一次交换只进行一次交换 p=namei; namei=namek; namek=p; void main() char *name=TOM,JHON,KATE, JACSON,MACEAL; int n=5, i; sort(name,n); for (i=0;in;i+) printf(%sn,namei);576.6 6.6 字符数组与指针字符数组与指针v在在C C语言程序中,可以用两种方法访问一个字符串。语言程序中,可以用两种方法访问一个字符串。 用字符数组存放一个

55、字符串,然后输出该字符串。用字符数组存放一个字符串,然后输出该字符串。 用字符指针指向一个字符串。可以不定义字符数组,用字符指针指向一个字符串。可以不定义字符数组,而定义一个字符指针。用字符指针指向字符串中的字符。而定义一个字符指针。用字符指针指向字符串中的字符。#includevoid main()char *string=I love China!;puts(string);【例例6-3】定义一个定义一个字符数组,对它初始字符数组,对它初始化,然后输出该字符化,然后输出该字符串。串。586.6 6.6 字符数组与指针字符数组与指针#include void main()char a= I

56、am a boy., b20;int i; for(i=0; ai!=0; i+) /用循环实现复制*(b+i)=*(a+i);*(b+i)=0;printf(string a is %sn, a); /输出两个字符串printf(string b is );for(i=0; bi!=0; i+)printf(%c, bi);printf(n);【例例6-5】将字符串将字符串a复制到字符串复制到字符串b中。中。59【例例6-6】从从10个数中找出其中最大值和最小值。个数中找出其中最大值和最小值。 6.7 6.7 指针变量作函数的参数指针变量作函数的参数#include void max_min

57、(int *x,int n,int *max,int *min);main()int i,a10=52,14,21,56,37,28,45,75,66,38,max,min;for(printf(The original array=),i=0;i10;i+)printf(%3d,ai);max_min(a,10,&max,&min);printf(nmax=%d min=%dn,max,min);void max_min(int *x, int n, int *max, int *min) int i;*max=*min=*x;for(i=1; in; i+, x+) if(

58、*max*x) *min=*x; 606.8 6.8 函数与指针函数与指针本节内容本节内容 6.8.2 函数指针作函数参数函数指针作函数参数 6.8.3 返回指针值的函数返回指针值的函数 6.8.1 指向函数的指针指向函数的指针616.8.1 6.8.1 指向函数的指针指向函数的指针v可以定义一个指针变量让它指向该函数的入口地可以定义一个指针变量让它指向该函数的入口地址,那么对函数的调用就可以通过指针变量完成址,那么对函数的调用就可以通过指针变量完成了。这个指针变量称为指向函数的指针变量,也了。这个指针变量称为指向函数的指针变量,也称为函数指针。称为函数指针。v定义函数指针的一般形式:定义函数

59、指针的一般形式: 数据类型数据类型 ( (* *指针变量名指针变量名)( );)( );v如如 int (int (* *p)( );p)( );v此处表示定义了指针变量此处表示定义了指针变量p p,指向一个函数的入口,指向一个函数的入口地址,地址,intint表示函数返回值的类型是整型,指针变表示函数返回值的类型是整型,指针变量量p p可以指向返回值类型相同的不同函数。可以指向返回值类型相同的不同函数。626.8.1 6.8.1 指向函数的指针指向函数的指针#includeint MAX(int x,int y) int z; z=(xy?x:y); return z;main() int

60、a,b,max; printf(please input a,b: ); scanf(%d,%d,&a,&b); max=MAX(a,b); printf(max=%dn,max);【例例6-7】分析如下程序运分析如下程序运行结果。行结果。636.8.1 6.8.1 指向函数的指针指向函数的指针#includeint MAX(int x,int y) int z; z=(xy?x:y); return z;main() int a,b,max; int (*p)(int,int); printf(please input a,b: ); scanf(%d,%d,&a,&

61、amp;b); p=MAX; max=(*p)(a,b); printf(max=%dn,max);原程序改写如左:原程序改写如左: 646.8.2 6.8.2 函数指针作函数参数函数指针作函数参数【例例6-8】用函数指针作参数,计算两数之和、差、积、商。用函数指针作参数,计算两数之和、差、积、商。#includevoid main() int a,b,add(int,int),dif(int,int),pro(int,int),quo(int,int); void process(int,int,int (*fun)(int,int); scanf(%d,%d,&a,&b); process(a,b,add); process(a,b,dif); process(a,b,pro); process(a,b,quo);void p

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论