第8章 指针.ppt

上传人:王申宇 文档编号:388651 上传时间:2018-10-12 格式:PPT 页数:67 大小:2.05MB
下载 相关 举报
第8章 指针.ppt_第1页
第1页 / 共67页
第8章 指针.ppt_第2页
第2页 / 共67页
第8章 指针.ppt_第3页
第3页 / 共67页
第8章 指针.ppt_第4页
第4页 / 共67页
第8章 指针.ppt_第5页
第5页 / 共67页
亲,该文档总共67页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

1、第8章 指针,主要内容,地址和指针的概念,变量的指针和指向变量的指针变量,数组与指针,字符串与指针,指向函数的指针,返回指针值的函数,指针数组和指向指针的指针,有关指针的数组类型和指针运算的小结,本章学习目标: 认识到用地址作为一种数据类型的重要性。 理解指针包括地址和类型两种属性。 掌握指针运算符&和*。 能够通过地址引用调用在被调函数与主调函数之间共享数据。 理解指针和数组的关系。 理解指向函数的指针的用法。,8.1 地址和指针的概念,指针:一个变量的地址。 指针变量:存放某一变量的地址(即指针)。,8.2 变量的指针和指向变量的指针变量 定义一个指针变量 定义的一般形式:基类型 *指针变

2、量名; 基类型:用来指定指针变量可以指向的变量的类型。将决定指针移动和运算时的移动量。 * :表示该变量为指针类型,例 int *p1,*p2;float *q ;static char *name;,注意: 1、int *p1, *p2; 与 int *p1, p2; 2、指针变量名是p1,p2 ,不是*p1,*p2 3、指针变量只能指向定义时所规定类型的变量 4、指针变量定义后,变量值不确定,应用前必须先赋值,&与*运算符:,取地址运算符 含义: 取变量的地址,指针运算符(“间接访问”运算符) 含义: 取指针所指向变量的内容,i_pointer-指针变量,它的内容是地址量 *i_point

3、er-指针的目标变量,它的内容是数据 &i_pointer-指针变量占用内存的地址,指针变量的初始化 一般形式:存储类型 数据类型 *指针名=初始地址值;,赋给指针变量, 不是赋给目标变量,例 int i;int *p=,变量必须已说明过 类型应一致,例 int i;int *p=,用已初始化指针变量作初值,指针变量赋值: int i, j; int *p1, *p2; p1=,指针变量的引用,例8.1 通过指针变量访问整型变量 #include void main( ) int a, b, *p1, *p2 ; a=100; b=10; p1= ,运行结果: a=100, b=10 *p1=

4、100, *p2=10 &a=ffd4, &b=ffd6 p1=ffd4, p2=ffd6 &p1=ffd8, &p2=ffda,关于 则 &* p1 &a (p1) &* p2 &b (p2) p2=&* p1 p2=&a,2. * & a:先进行&a得a的地址,再对a的地址进行* 运算 即指向a地址所指向的变量,就是a ,其值是100 3. 运算符 * ,+ :优先级为2, 结合性:从右到左 (* p1)+ a+ * p1+ * (p1+) 意即: p1原指向a , 现在指向下一个地址了。,例8.2 输入a和b两个整数,用指针方法按先大后小顺序输出 #include void main(

5、) int *p1, *p2, *p, a, b; scanf(“%d%d”, ,运行情况: 5,9 a=5, b=9 max=9,min=5,指针变量作为函数参数地址传递,例8.3a 将数从大到小输出 #include void swap(int x,int y) int temp;temp=x;x=y;y=temp; void main() int a,b;scanf(“%d,%d“, ,运行结果: 5 , 9 5 , 9,5,9,5,5,9,COPY,例8.3b 将数从大到小输出 #include void swap(int *p1, int *p2) int *p;p=p1;p1=p2

6、;p2=p; void main() int a,b;int *pointer_1,*pointer_2;scanf(“%d,%d“, ,5,9,2000,2002,2000,2000,2002,运行结果:5,9,例8.3 将数从大到小输出(使用指针变量作函数参数) #include void main() void swap(int *p1, int *p2);int a,b;int *pointer_1,*pointer_2;scanf(“%d,%d“,运行情况: 5,9 9,5,问题:函数调用结束后, 分配给p1,p2,temp单元释放否?,5,9,2000,2002,5,9,5,地址传

7、递,例8.5 输入a,b,c3个整数,按从大到小输出 #include void main( ) void exchange(int *q1, int *q2, int *q3); int a,b,c,*p1,*p2,*p3; scanf(“%d,%d,%d”,运行情况: 9 , 0 , 10 10 , 9 , 0,void swap(int *pt1, int *pt2) int temp; temp=*pt1; *pt1=*pt2; *pt2=temp;,void exchange(int *q1, int *q2, int *q3) void swap(int *pt1, int *pt

8、2); if(*q1 *q2) swap(q1, q2); if(*q1 *q3) swap(q1, q3); if(*q2 *q3) swap(q2, q3);,8.3 数组与指针Q1:如何用指针指向数组?Q2:如何用指针访向数组元素?,回顾数组名代表什么?如何访向数组元素及地址?指针变量里存放的是什么?,int a5; / a代表这组数的首地址,a2代表第3个元素,&a2代表第3个元素地址,int *p; / p里存放的是内存单元地址,Q1:如何用指针指向数组?int a5=1,2,3,4,5, *p;p= ;p= ;,a,&a2,Q2:如何用指针访向数组元素?int a5=1,2,3,4

9、,5, *p=a;,P+;/指针移动,P-;,*P=5;,/给p所指向的数据元素赋值,表示数组元素的两种方法:, 变址运算符 ai *(a+i),ai pi *(p+i) *(a+i), 下标法: #include void main() int a10;int i;for(i=0; i10; i+)scanf(“%d“,运行情况: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0,例8.6 用三种方法输出数组中全部元素的值, 用数组名: #include void main() int a10;int i;for(i=0; i10; i+)scanf(“%d“,

10、 指针法: #include void main() int a10;int *p,i;for(i=0; i10; i+)scanf(“%d“, 指针法和指针下标: #include void main() int a10;int *p,i;for(i=0; i10; i+)scanf(“%d“,例8.7 用指针变量输出元素 #include void main() int *p,i,a10;p=a;for(i=0;i10;i+)scanf(“%d”,p+); printf(“n”);for(i=0;i10;i+,p+)printf(“%d”,*p);printf(“n”); ,运行情况: 1

11、 2 3 4 5 6 7 8 9 0 22153 234 0 0 30036 25202 11631 8259 8237 28483,例8.7 用指针变量输出元素 #include void main() int *p,i,a10;p=a;for(i=0;i10;i+)scanf(“%d”,p+); printf(“n”);p=a; /*或者p= ,能正确输出吗?,运行情况: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0,原因?,用数组名作函数参数,数组名作函数参数 void main( ) f(int arr , int n); int array10; f

12、(array, 10); void f(int arr , int n) ,编译时arr按指针变量处理,所以,此句与f(int *arr , int n)等价。,例8.8 将数组a中n个整数按相反顺序存放。思路:数组元素头尾对调。四种调用方式。,m=4, 实参与形参均用数组 #include void main() void inv(int x , int n);int i,a10=3,7,9,11,0,6,7,5,4,2;printf(“The original array:n“);for(i=0;i10;i+) printf(“%d,“ai);printf(“n“);inv(a,10);p

13、rintf(“The array has been inverted:n“);for(i=0;i10;i+) printf(“%d,“,ai);printf(“n“); void inv(int x , int n) int temp,i,j,m=(n-1)/2;for(i=0;i=m;i+) j=n-1-i;temp=xi; xi=xj; xj=temp; return; , 实参用数组,形参用指针变量 #include void main() void inv(int *x, int n);int i,a10=3,7,9,11,0,6,7,5,4,2;printf(“The origina

14、l array:n“);for(i=0;i10;i+) printf(“%d,“ai);printf(“n“);inv(a,10);printf(“The array has been inverted:n“);for(i=0;i10;i+) printf(“%d,“,ai);printf(“n“); void inv(int *x, int n) int temp,*p,*i,*j,m=(n-1)/2;i=x; j=x+n-1; p=x+m;for(;i=p;i+,j-) temp=*i; *i=*j; *j=temp; return; ,例8.8 实参与形参均用指针变量 #include

15、void main() void inv(int *x, int n);int i,arr10,*p=arr;printf(“The original array:n“);for(i=0;i10;i+,p+)scanf(“%d“,p);p=arr; inv(p,10);printf(“The array has been inverted:n“);for(p=arr;parr+10;p+)printf(“%d“,*p);printf(“n“); void inv(int *x, int n) int *p, m, temp,*i,*j;m=(n-1)/2;i=x; j=x+n-1; p=x+m

16、;for(;i=p;i+,j-) temp=*i; *i=*j; *j=temp; return;,此句用意?, 实参用指针变量,形参用数组 #include void main() void inv(int x , int n);int i,a10,*p=a;for(i=0;i10;i+,p+)scanf(“%d“,p);p=a;inv(p,10);printf(“The array has been inverted:n“);for(p=arr;parr+10;p+)printf(“%d “,*p);printf(“n “); void inv(int x , int n) int t,i

17、,j,m=(n-1)/2;for(i=0;i=m;i+) j=n-1-i;t=xi; xi=xj; xj=t; return; ,例 从10个数中找出其中最大值和最小值为了得到两个结果值,用两个全局变量max和min。, 实参和形参均用数组 int max, min; /* 全局变量*/ void max_min_value(int array ,int n) int *p, *array_end; array_end=array+n; /*指向数组最后一个元素的后面 */max=min=*array; /* 相当于max=min=array0 */for(p=array+1; p max)

18、max=*p; else if(*pmin) min=*p; main( ) int i, number10; printf(“enter 10 integer numbers: n”); for(i=0;i10;i+) scanf(“%d”, , 实参和形参均用指针变量 int max, min; /* 全局变量*/ void max_min_value(int *array,int n) int *p, *array_end; array_end=array+n; /*指向数组最后一个元素的后面 */max=min=*array; /* 相当于max=min=array0 */for(p=

19、array+1; p max) max=*p; else if(*pmin) min=*p; main( ) int i, number10,*p; p=number; /* 使p指向number数组 */ printf(“enter 10 integer numbers: n”); for(i=0;i10;i+,p+) scanf(“%d”,p); printf(“the 10 integer numbers:n“);for(p=number,i=0;i10;i+,p+) printf(“%d “,*p);p=number;max_min_value(p,10); printf(“nmax=

20、%d, min=%dn”, max, min); ,归纳:用数组做函数参数有如下四种情况: 1、实参形参都用数组名:int a10; inv(int x ,int n)inv(a,10) . 2、实参用数组名,形参用指针变量:int a10; inv(int *x,int n)inv(a,10) . 3、实参形参都用指针变量:int a10; inv(int *x,int n)int *p=a; inv(p,10) 4、实参用指针变量,形参用数组名:int a10; inv(int x ,int n)int *p=a; .inv(p,10), 实参用指针变量,形参用数组 #include vo

21、id main() void sort(int x , int n);int *p,i,a10;p=a;for(i=0;ixk) k=j;if(k!=i)t=xi;xi=xk;xk=t; ,例8.9 用选择法对10个整数排序,多维数组与指针 int a34=1,3,5,7,9,11,13,15,17,19,21,23;,行地址,列元素地址,列元素地址:a1+3 *(a+1)+3 &a13,指向多维数组的指针变量 指向数组元素的指针变量,例8.12 用指针变量输出数组元素的值 #include void main() static int a34=1,3,5,7,9,11,13,15,17,19

22、,21,23;int *p;for(p=a0;pa0+12;p+) if(p-a0)%4=0) printf(“n“);printf(“%4d “,*p); ,指向由m个元素组成的一维数组的指针变量 定义形式: 数据类型 (*指针名)一维数组维数;例 int (*p)4;,( )不能少 int (*p)4与int *p4不同,p的值是一维数组的 首地址,p是行指针,可让p指向二维数组某一行如 int a34, (*p)4=a;,一维数组指针变量维数和 二维数组列数必须相同,例8.13 输出二维数组任一行任一列元素的值 #include void main() static int a34=1,

23、3,5,7,9,11,13,15,17,19,21,23;int (*p)4, i, j;p=a;scanf(“i=%d, j=%d”, ,运行结果: i=1, j=2a12=13,8.4 字符串与指针 字符串的表示形式 字符串: 用双引号括起的一串字符。,char string =“I love China!”;,char *string=“I love China!“;,改动后的例8.16 #include void main( ) char *string=“I love China!”;printf(“%sn”,string);string+=7;while(*string) putc

24、har(*string);string+;,*string!=0,输出: I love China!China!,用下标法存取字符串中的字符,例8.18 将字符串a复制为字符串b #include void main( ) char a =“I am boy.“,b20;int i;for(i=0;*(a+i)!=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“); ,运行结果: string a

25、 is: I am boy. string b is: I am boy., bi=ai,地址访问: a 复制到b ,下标法输出,例8.19 用指针变量实现例8.18 #include void main( ) char a =“I am boy.”,b20;char *p1=a,*p2=b;int i;for( ; *p1!=0 ; p1+,p2+) *p2=*p1;*p2=0; printf(“string a is: %sn”, a );printf(“string b is: %sn”, b ); ,运行结果: string a is: I am boy. string b is: I

26、 am boy.,p1 p2,运行结果: string a is: string b is:,p1=a; p2=b;,字符指针作函数参数,例8.20 用函数调用实现字符串的复制,用字符数组作参数 #include void main() void copy_string(char from,char to);char a =“I am a teacher.“;char b =“You are a student.“;printf(“string_a=%sn string_b=%sn“,a,b);printf(“copy string_a to string_b: n“);copy_string

27、(a,b); /* 数组名作参数是地址传递*/printf(“nstring_a=%snstring_b=%sn“,a,b); void copy_string(char from,char to) int i=0;while(fromi!=0) toi=fromi; i+; toi=0; ,字符指针变量作形参 #include void main() void copy_string(char *from,char *to);char *a=“I am a teacher.“;char *b=“You are a student.“;printf(“string_a=%sn string_b

28、=%sn“,a,b);printf(“copy string_a to string_b: n“);copy_string(a,b);printf(“nstring_a=%snstring_b=%sn“,a,b); void copy_string(char *from,char *to) for(;*from!=0;from+,to+)*to=*from;*to=0; ,对使用字符指针变量和字符数组的讨论 char *cp; 与 char str20; 的区别 str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址 赋值方式: 字符数组只能对元素赋值。 char str20; s

29、tr=“I love China!”; () 字符指针变量可以用: char *cp; cp=“I love China!”; () 赋初值:char *cp=“China!“; 等价 char *cp; cp=“China!”; char str14=“China“;不等价char str14; str =“China“ (),用指针变量指向的格式字符串代替printf中的格式字符串(可变格式输出函数)char *format;format=“a=%d,b=%fn“;printf(format,a,b); 相对于:printf(“a=%d,b=%fn“a,b); 可以用字符数组实现:char

30、 format =“a=%d,b=%fn“;printf(format,a,b);,判断和修正:,char str=“Hello!”; () char str=“Hello!”; () char str=H,e,l,l,o,!; () char *cp=“Hello”; () int a=1,2,3,4,5; () int *p=1,2,3,4,5; (),char str10,*cp; int a10,*p; str=“Hello”; () cp=“Hello!”; () a=1,2,3,4,5; () p=1,2,3,4,5; (),8.5 指向函数的指针 用函数指针变量调用函数。 函数指

31、针:函数在编译时被分配的入口地址,用函数名表示。函数指针指向的是程序代码存储区。,函数指针变量定义形式: 数据类型 (*指针变量名)( ); 如 int (*p)();,函数返回值的数据类型,专门存放函数入口地址 可指向返回值类型相同的不同函数,( )不能省 int (*p)() 与 int *p()不同,函数指针变量赋值:如 p=max;,函数调用形式: c=max(a,b); c=(*p)(a,b); 对函数指针变量pn, p+, p-无意义,函数指针变量指向的函数必须有函数说明,例8.22 求a和b中的大者,一般方法: #include void main() int max(int ,

32、int);int a,b,c;scanf(“%d,%d“,通过指针变量访问函数 #include void main() int max(int , int); int (*p)(int , int);int a,b,c;p=max;scanf(“%d,%d“,8.6 返回指针值的函数 函数定义形式: 类型标识符 *函数名(参数表); 例 int *f(int x, int y),例8.25:有若干学生成绩,要求输入学生序号后,能输出该学生全部成绩。用指针函数实现。,#include void main() float score 4=60,70,80,90,56,89,67,88,34,78

33、,90,66;float *search(float (*pointer)4,int n);float *p;int i,m;printf(“Enter the number of student:“);scanf(“%d“,形参指向一维数组的指针变量,指向实型变量的指针变量,接受search函数返回的指向某学生0门课程地址的指针变量,例8.26 找出例8.25中有不及格课程的学生及其学号 #include void main() float score 4=60,70,80,90,56,89,67,88,34,78,90,66;float *search(float (*pointer)4)

34、;float *p; int i,j;for(i=0;i3;i+) p=search(score+i);if (p=*(score+i) printf(“No. %d scores: “,i);for(j=0;j4;j+)printf(“%5.2ft“,*(p+j); float *search(float (*pointer)4) int i;float *pt;pt=NULL;for(i=0;i4;i+)if(*(*pointer+i)60) pt=*pointer;break;return(pt); ,8.7 指针数组和指向指针的指针 用于处理二维数组或多个字符串 指针数组的概念 定义:

35、数组中的元素均为指针变量 定义形式:存储类型 类型名 *数组名数组长度;例 int *p4;,指针所指向变量的数据类型,区分int *p4与int (*p)4,指针数组赋值与初始化,赋值: main() int b23,*pb2;pb0=b0;pb1=b1; ,初始化: main() int b23,*pb =b0,b1; ,指针数组赋值与初始化,二维数组与指针数组区别:,char name59=“gain”,“much”,“stronger”, “point”,“bye”;,char *name5=“gain”,“much”,“stronger”, “point”,“bye”;,二维数组存储

36、空间固定 字符指针数组相当于可变列长的二维数组,指针数组元素的作用相当于二维数组的行名 但指针数组中元素是指针变量 二维数组的行名是地址常量,例 用指针数组处理二维数组,main() int b23,*pb2;int i,j;for(i=0;i2;i+)for(j=0;j3;j+)bij=(i+1)*(j+1);pb0=b0;pb1=b1;for(i=0;i2;i+)for(j=0;j3;j+,pbi+)printf(“b%d%d:%2dn“,i,j,*pbi); ,例8.26 对字符串排序(简单选择排序),i=0,例8.26 对字符串排序(简单选择排序) #include #include

37、void main() void sort(char *name ,int n); void print (char *name ,int n);char *name=“Follow me“,“BASIC“,“Great Wall“,“FORTRAN“,“Computer design“;int n=5;sort(name,n);print(name,n); void sort(char *name ,int n) char *temp;int i,j,k;for(i=0;i0) k=j;if(k!=i) temp=namei; namei=namek; namek=temp; ,void p

38、rint(char *name , int n) int i ;for(i=0; in; i+)printf(“%sn“,name i ; ,name0,name1,name2,name3,name4,name,Great Wall,FORTRAN,Computer,Follow me,BASIC,指向指针的指针多级指针(了解) 一级指针:指针变量中存放目标变量的地址,例 int *p; int i=3;p=,一级指针,单级间接寻址,例 int *p1; int *p2;int i=3;p2=,二级指针,一级指针,目标变量,二级间接寻址,二级指针:指针变量中存放一级指针变量的地址,如果:cha

39、r *name =“Follow me“;char *p;p=name+2;则:printf(“%sn“,*p); 输出:Great Wall,定义形式:存储类型 数据类型 *指针名;如:char *p,指针本身的存储类型,最终目标变量的数据类型,二级指针与指针数组的关系int *p 与 int *q10 指针数组名是二级指针常量 p=q; p+i 是qi的地址 指针数组作形参,int *q 与int *q完全等价;但作为变量定义两者不同 系统只给p分配能保存一个指针值的内存区;而给q分配10块内存区,每块可保存一个指针值,指针数组作main函数的形参(掌握) main函数的一般调用形式: m

40、ain( ) main函数的有参数调用形式 :main( int argc , char *argv ) 其中( int argc , char *argv 是形参,可以多个: int argc; 命令名和所有参数个数之和 char *argv ; 各元素是指针,分别指向各参数字符串 在实际运行程序时,实参和命令名(C程序编译和连接后得到的可执行文件名)以命令行形式给出:命令名 参数1 参数2 参数n 回车,例 用命令行参数方式运行程序,/*test.c*/ main(int argc, char *argv) while(argc1) +argv;printf(“%sn“,*argv);-a

41、rgc; ,1. 编译、链接test.c,生成可执行文件test.exe 2. 在DOS状态下运行(test.exe所在路径下),例如: C:TC test.exe hello world!,运行结果:helloworld!,main(int argc, char *argv) while(argc0)printf(“%sn“,*argv+); ,例如: C:TC test.exe hello world!,运行结果:testhelloworld!,8.8 动态内存分配与指向它的指针变量1、内存动态分配相关函数(头文件:stdlib.h),2、void指针类型定义时不指定指向哪一类数据 用动态

42、存储分配函数时返回void指针 它的值赋给另一指针变量时,要强制类型转换 例:char *p1;void *p2;p1=(char *)p2;或p2=(void *)p1;void *fun(char ch1,char ch2) 返回“空类型”地址 P1=(char *)fun(ch1,ch2); 引用时要类型转换,8.9 有关指针的数据类型和指针运算的小结 有关指针的数据类型的小结,指针运算小结 指针变量加(减)一个整数如:p+;p-;p+i;p-i;p+=i;p-=i等,加减的值与类型有关。 指针变量赋值p=&a (将变量a的地址赋给p)p=array;(将数组array首地址赋给p)p=

43、&arrayi;(将数组array第i个元素的地址赋给p)p=max;(max为已定义的函数,将max函数的入口地址赋给p)p1=p2;(p1和p2都是指针变量,将p2的值赋给p1) (3) 指针变量不指向任何变量,即取空值。表示为:p=NULL; (4) 两个指针变量可以相减如果两个指针变量指向同一个数组为元素,则两个指针变量值之差是两个指针之间的元素个数。但p1+p2并无实际意义。 (5) 两个指针变量比较如果两个指针变量指向同一个数组为元素,则可以进行地址比较。,例 下列定义的含义 int *p3; int (*p)3; int *p(int); int (*p)(int); int *(*p)(int); int (*p3)(int); int *(*p3)(int);,本章小结指针C语言的一个重要概念,也是C语言的一个重要特色。正确灵活地运用指针可以有效地表达复杂的数据结构,动态地分配内存以及方便地处理字符串,有效而方便地使用数组,可以直接处理内存等。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 教学课件 > 大学教育

copyright@ 2008-2019 麦多课文库(www.mydoc123.com)网站版权所有
备案/许可证编号:苏ICP备17064731号-1