第9章指针.ppt
《第9章指针.ppt》由会员分享,可在线阅读,更多相关《第9章指针.ppt(84页珍藏版)》请在三一文库上搜索。
1、第9章 指针,指针是C语言最具特色的语言成分,它是C语言的精华,同时又是C语言的难点。正确而灵活地运用指针,可以有效地表示复杂的数据结构;能高效地使用数组和字符串,能动态分配内存,在调用函数后改变有关变量的值,能直接处理内存地址,能完成有关文件的操作。若没有掌握指针,就没有真正掌握C语言,因此应在本章上多花工夫,多思考,多上机,在实践中掌握它。,9.1地址和指针的概念,9.1.1 内存地址内存中存储单元的编号 计算机硬件系统的内存储器中,拥有大量的存储单元,一个字节为一个单元,内存是以字节为单位来存储数据的。为了方便管理,必须为每一个存储单元编号,这个编号就是存储单元的“地址”。每个存储单元都
2、有一个惟一的地址。如图9-1,图9-1,9.1.2 指针和指针变量,指针即是地址。 指针变量专门用于存放其它变量首地址的变量。 例如:把2000存放在变量p中,通过p指向x变量,可以间接访问x变量。如:图9-1 这里的p是指针变量,它指向x变量,x变量的首地址2000是x变量的指针。,指针的概念 变量与地址,程序中: int i; float k;,内存中每个字节有一个编号-地址,i,k,编译或函数调用时为其分配内存单元,变量是对程序中数据 存储空间的抽象,指针与指针变量 指针:一个变量的地址 指针变量:专门存放变量地址的变量叫,2000,指针,指针变量,变量的内容,变量的地址,9.2指针变量
3、的定义与应用,9.2.1指针变量的定义 一般格式: 基类型 * 指针变量名 在定义指针变量时要注意2点: (1)指针变量前面的*号表示变量的类型为指针变量。 (2)在定义指针变量时必须指定基类型,它表示此指针是指向什么类型的变量。 如: int *p; /* 变量p是指针变量,它指向整型变量 */ char *q; /* 变量q是指针变量,它指向字符型变量 */,9.2.2指针变量的引用,指针变量中只能存放地址(指针),不能将一个整型量(或任何其他非地址类型的数据)赋给一个指针变量。下面的赋值是不合理的: int *p; p=100; 与指针变量的引用的两个相关运算: 1&取地址运算符,它的作
4、用是取得变量所占用的存储单元的首地址。 2*指针运算符(或称“间接访问”运算符)。,&与*运算符 含义,含义: 取变量的地址 单目运算符 优先级: 2 结合性:自右向左,含义: 取指针所指向变量的内容 单目运算符 优先级: 2 结合性:自右向左,两者关系:互为逆运算 理解,i_pointer-指针变量,它的内容是地址量 *i_pointer-指针的目标变量,它的内容是数据 &i_pointer-指针变量占用内存的地址,i_pointer &i &(*i_pointer) i *i_pointer *(&i),i_pointer = &i = &(*i_pointer) i = *i_point
5、er = *(&i),例题9.1输出两个整数的值 /*例题源代码文件名:LT9_1.C*/ main( ) int a,b; int * p1,*p2; /*定义p1,p2两个指针变量*/ a=20; b=30; p1= /*将p1,p2指向的内存单元的值输出*/ ,运行结果: 200,30 200,30,注意: (1)在定义指针变量的同时也可以初始化。 int a,b; int *p1,*p2; a=20; b=30; p1=,(2)一旦将变量a的地址赋给指针变量p1,那么*p1与a是等价的。 (3)在指针变量定义语句中的星号“*”,是指针变量的标识符,不是指针运算。如例9-1第3行。除了指
6、针变量定义语句,在其他语句的“*”号都表示是指针运算。,例9.2 输入a,b两个整数,按降序(从大到小)顺序输出a、b的值。 main( ) int *p1,*p2,*p,a,b; scanf(“%d,%d”, ,运行结果: 5,9 a=5,b=9 max=9,min=5,当运行时输入5,9时,a=5,b=9, if(*p1*p2)语句表示如果p1指向的a的值小与p2指向的b的值,则将p1与p2交换。交换前的情况见图9-2 (a),交换后的情况见图9-2(b)。,交换前图9-2 (a),交换后图9-2 (b),9.3指针变量作为函数参数,函数的参数不仅可以是整型、实型、字符型等数据,还可以是指
7、针变量。它的作用是将一个变量的地址传送到另一个函数中。指针变量既可以作为函数的形参,也可以作为函数的实参。 例题9.3输入两个整数,按从大到小顺序输出。 /*例题源代码文件名:LT9_3.C*/ swap( int *p1,int *p2) int p; p=*p1; *p1=*p2; *p2=p; ,main( ) int a,b; int *x1,*x2; scanf(“%d,%d”, ,运行情况: 输入5 9 max=9,min=5,说明: (1)swap是用户定义的函数,它的作用是通过形参指针变量p1,p2分别指向a,b来交换a,b两个变量的值。 (2)程序运行时,先执行main函数,
8、输入a 和b的值(输入5 和9),然后将a和b的地址给指针变量x1,x2,是x1,x2分别指向a,b。见图9-3(a)接着执行if语句,由于ab,因此执行swap函数,在调用函数时,将实参指针变量x1和x2的值(地址)传给形参指针变量p1和p2。见图9-3(b),接着执行swap函数的函数体,通过形参指针变量p1,p2分别指向a,b来交换a,b两个变量的值。交换后的情况见图9-3(c)。调用结束后,p1p2不复存在(已释放),情况如图9-3(d)最后在主函数中输出的a,b的值已是经过交换的值。(a=9,b=5),调用前,调用开始时,调用结束时,调用后,swap(int *p1,int *p2)
9、 int *p; p=p1; p1=p2; p2=p; ,main( ) int a,b; int *pt1,*pt2; scanf(“%d,%d”, ,思考:例9.4以下程序的运行结果。,为什么运行情况是: 输入5, 9 5,9 解析:调用前pt1a, pt2b,调用时pt1的值(地址)传给p1, pt2的值(地址)传给p1,使得p1a, p2b.但是在子函数中交换的是p1和p2两个指针内的地址值,使得p1b,p2a.当调用结束,p1,p2形参指针变量释放消失,返回主函数时仍然pt1a, pt2b,所以输出pt1,pt2所指向变量的值,还是a,b的值5,9。因而不能企图通过改变指针形参的值而
10、使指针实参的值改变。因为实参与形参的数据传递是单向的“值传递”方式,实参形参。,9.4指针与数组,C语言中指针和数组有着极密切的联系。数组处理的是一些具有相同类型的元素,用指针也能同样的工作,两者相比而言,数组的下标法易于理解,而指针表示法来处理数组元素,能产生高质量的目标代码,提高程序执行效率。,9.4.1指向数组元素的指针变量的定义,int a10; int *p; p= /* a与&a0等价*/ 因为数组名a代表数组的首地址,也就是第0号元素的地址。,9.4.2指针与一维数组的关系,如:int a10,*p; p=a; 可以用下标法和指针法表示,数组元素表示方法, 变址运算符 ai *(
11、a+i),ai pi *(p+i) *(a+i),例题9.5运用下标法和指针法 /*例题源代码文件名:LT9_5.C*/ main() int a5,*p,i; for(i=0;i5;i+) ai=i+1; p=a; for(i=0;i5;i+) printf(“*(a+%d)=%dn“,i,*(a+i); for(i=0;i5;i+) printf(“a%d=%dn“,i,ai); ,运行结果: *(a+0)=1 *(a+1)=2 *(a+2)=3 *(a+3)=4 *(a+4)=5 a0=1 a1=2 a2=3 a3=4 a4=5,例9.6用指针变量指向数组元素 /*例题源代码文件名:LT
12、9_6.C*/ main( ) int a5; int *p,x; for(x=0;x5;x+) scanf(“%d”, /*号表示空格*/ ,运行结果: 12 13 15 16 20(输入的数据) 12 13 15 16 20 (输出结果),例题9.7使用指向数组的指针变量来引用数组元素。 /*例题源代码文件名:LT9_7.C*/ main() int a10, *p=a, i; printf(“Input 10 numbers: ”); for(i=0; i10; i+) scanf(“%d”, p+i); /*使用指针变量来输入数组元素的值*/ printf(“a10: ”); for(
13、i=0; i10; i+) printf(“%d ”, *(p+i); /*使用指向数组的指针变量输出数组*/ printf(“n”); ,程序运行情况: Input 10 numbers: 0 1 2 3 4 5 6 7 8 9 a10: 0 1 2 3 4 5 6 7 8 9,scanf(“%d”, p+i);语句中p+i的前面不能加&,因为p+i表示地址。,例9.8通过指针变量输出a数组的10个元素。 /*例题源代码文件名:LT9_8.C*/ main( ) int n,a10,*p; p=a; for(n=0;n10;n+) scanf(“%d”,p+); /*使用指针表示数组各元素的
14、地址*/ printf(“n”); p=a; /*使指针重新指向a数组的第一个元素*/ for(n=0;n10;n+,p+) printf(“%2d”,*p); /*使用指向数组的指针变量,顺序输出数组各元素*/ ,运行情况: 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10,如果程序去掉第7行语句p=a;则运行情况为: 1 2 3 4 5 6 7 8 9 10 22153 234 0 0 30036 25202 11631 8259 8237 28483 显然输出的数值不是a数组中各元素的值。原因是指针变量p的初始值为a数组的首地址,但经过第一个for循环读
15、入数据后,p已指向a数组的末尾。因此,在执行第二个for循环时,p的起始值不是a数组的首地址了,而是a+10。所以执行循环时,每次p+,p指向的是a数组下面的10个元素,而这些单元的值是不可预料的。故必须在第二个for循环前有p=a;语句将指针返回数组的开头。,指针的运算 1.指针变量的赋值运算 p= (指针变量p2值p1) 不能把一个整数p,也不能把p的值整型变量,如 int i, *p; p=1000; () i=p; (),指针变量与其指向的变量具有相同数据类型,9.4.3指针变量的运算,2.指针的算术运算: pi p id (i为整型数,d为p指向的变量所占字节数) p+, p-, p
16、+i, p-i, p+=i, p-=i等 若p1与p2指向同一数组,p1-p2=两指针间元素个数(p1-p2)/d p1+p2 无意义,例 p指向float数,则 p+1 p+1 4,例 p指向int型数组,且p= 则p+1 指向a1,例 int a10; int *p=,例 int a10; int *p1=,1,3两个指针变量相减 p1与p2指向同一数组,p1-p2=两指针间元素个数,而不是指针的地址之差。 p1+p2 无意义。 例 int a10; int *p1= 4.指针变量的关系运算 若p1和p2指向同一数组,则 p1p2 表示p1指的元素在后 p1=p2 表示p1与p2指向同一元
17、素,若p1与p2不指向同一数组,比较无意义 p=NULL或p!=NULL 5*p+等价于*(p+)因为+和*优先级相同,结合方向为自右向左。 6*(p+)与*(+p)作用不同。前者是先取*p值,后使p加1。后者是先使p加1,在取*p的值。 7(*p)+表示p 所指向的元素值加1。 若p=则(*p)+表示a2的值加1,如果a2=3, (a2)+=3+1=4。,9.4.4引入指针变量后再论数组作函数的参数,本章引入指向数组的指针变量后,数组及指向数组的指针变量作为函数参数时,可有4中等价的形式(本质上是一种,即实参向形参传递的是地址) 实参是数组名,形参是数组。 main( ) f(int x ,
18、int n) int a10; f(a,10) ,2.实参是数组名,形参是指针变量 main( ) f (int *x, int n) int a10; f(a,10); 3.实参和形参都是指针变量 main( ) f (int *x, int n) int a10,*p; p=a; f (p,10); ,4.实参是指针变量,形参是数组。 main( ) f (int x , int n) inta10,*p; p=a; f (p,10); ,9.5程序举例,例题9.9实参是数组名,形参是指针变量的函数调用。 /*例题源代码文件名:LT9_9.C*/ int min_value(int *p,
19、 int n) /*形参是指针变量*/ int i,min; min=*p ; /*这里*p=a0,所以min=a0*/ for(i=0;in;i+) if(*(p+i)min) min=(*p+i); return (min) ,main( ) int a =-1,9,8,5,25,-50,0,6; int minv; minv=min_value(a,7); /*实参是数组名*/ printf(“minv=%d”,minv); ,运行结果:-50,例题9.10将数组a中数据逆序存放后输出。 /*例题源代码文件名:LT9_10.C*/ 编程思路: 先给数组初始化赋值,调用子函数,子函数的功能
20、是将数组中数据逆序存放,方法如图9-7。按箭头所示进行交换。,inver(int *b,int n) int *i,*j,t; for(i=b,j=b+n-1;ij;i+,j-) t=*i; *i=*j; *j=t; ,main( ) int a8=1,2,3,4,5,6,7,8 ; int i; inver(a,8); printf(“the inverted array is:n“); for(i=0;i8;i+) printf(“%4d“,ai); printf(“n“); ,运行结果: 8 7 6 5 4 3 2 1,解析,本例题实参是数组名a对应形参指针变量b,a的首地址传给b,在i
21、nver函数中,i开始指向数组的0号元素,j指向数组的最后一个元素,借助t变量a0与a7进行交换;然后 a1与a6进行交换;依次类推完成将数组中数据逆序存放。返回主函数后,用for循环输出逆序存放好的数据。,9.6指向二维数组的指针和指针变量,用指针变量指向一维数组,也可以指向二维数组。但在概念上和使用上,二维数组的指针比一维数组指针要复杂的多。 1回顾一维数组的地址 int a8,*p; p=a; 地址:a , a+1 ,a+2 ,a+7或p, p+1,p+2,p+3,p+7 元素表示:,2二维数组的地址与元素 定义一个二维数组: int a34=1,3,5,7,9,11,13,15,17,
22、19,21,23; a是数组名。将a数组看成3个一维数组组成。3个一维数组名为a0,a1,a2,每个一维数组又包含4个元素,如:a0代表的一维数组又包含元素a00,a01,a02,a03。,对于二维数组: (1)a是数组名, 包含三个元素 a0,a1,a2 (2)每个元素ai 又是一个一维 数组,包含4个 元素,int a34;,基类型,行指针与列指针,对二维数组 int a34,有 a-二维数组的首地址,即第0行的首地址 a+i-第i行的首地址 ai *(a+i)-第i行第0列的元素地址 ai+j *(a+i)+j -第i行第j列的元素地址 二维数组的元素表示为: *(ai+j) *(*(a
23、+i)+j) aij,a+i=&ai=ai=*(a+i) =&ai0, 值相等,含义不同 a+i &ai,表示第i行首地址,指向行 ai *(a+i) &ai0,表示第i行第0列元素地址,指向列,二维数组元素表示形式: (1)a12 (2)*(a1+2) (3)*(*(a+1)+2) (4)*(&a00+1*4+2),地址表示: (1) a+1 (2) &a10 (3) a1 (4) *(a+1) (5)(int *) (a+1),地址表示: (1) &a12 (2) a1+2 (3) *(a+1)+2 (4)&a00+1*4+2,在此对ai的性质作进一步说明。对于ai这种表示形式,如果a是一
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 指针
链接地址:https://www.31doc.com/p-2567561.html