C语言程序与设计:第8章指针.ppt

上传人:max****ui 文档编号:13559967 上传时间:2020-06-22 格式:PPT 页数:72 大小:1.98MB
收藏 版权申诉 举报 下载
C语言程序与设计:第8章指针.ppt_第1页
第1页 / 共72页
C语言程序与设计:第8章指针.ppt_第2页
第2页 / 共72页
C语言程序与设计:第8章指针.ppt_第3页
第3页 / 共72页
资源描述:

《C语言程序与设计:第8章指针.ppt》由会员分享,可在线阅读,更多相关《C语言程序与设计:第8章指针.ppt(72页珍藏版)》请在装配图网上搜索。

1、第八章 指针,C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存,能直接处理内存地址 得到多于一个的函数返回值,主要内容,指针的概念 变量的指针 数组的指针与字符串的指针 函数的指针与返回指针值的函数 指针的指针,8.1 地址与指针,程序中: int i; float x;,内存中每个字节有一个编号地址,i 的值,x 的值,编译或函数调用时为其分配内存单元,变量是对程序中数据 存储空间的抽象,变量与地址,指针与指针变量 指针:一个变量的地址。 指针变量:专门存放地址的变量。,2000,指针,变量的内容,变量的地址, -直接访问,3,例 *i_pointe

2、r = 20; -间接访问,20,8.2 指针变量,指针变量的定义 一般形式: 存储类型 数据类型 *指针变量名;,合法标识符,指针变量本身的存储类型,指针的目标变量的数据类型,表示定义指针变量 不是*运算符,例 int *p1,*p2; float *q ; static char *name;,注意: 1、int *p1, *p2; 与 int *p1, p2 的区别; 2、指针变量名是p1,p2,不是*p1,*p2; 3、指针变量只能指向定义时所规定类型的变量; 4、指针变量定义后,变量值不确定,使用前必须先赋值。,指针变量的初始化 一般形式:存储类型 数据类型 *指针名=初始地址值;,

3、赋给指针变量, 不是赋给目标变量,例 int i; int *p=,变量必须已说明过 类型应一致,例 int i=10; int *p=,用已初始化指针变量作初值,例 main( ) int i; static int *p= . (),不能用auto变量的地址 去初始化static型指针,例 main( ) int i=10; int *p; *p=i; printf(“%d”,*p); ,危险!,例 main( ) int i=10, k; int *p; p= ,指针变量必须先赋值,再使用,零指针与空类型指针 零指针:(空指针) 定义:指针变量值为零 表示: int * p=0;,p指向

4、地址为0的单元, 系统保证该单元不作它用 表示指针变量值没有意义,#define NULL 0 int *p=NULL:,p=NULL与未对p赋值不同 用途: 避免指针变量的非法引用 在程序中常作为状态比较,例 int *p; . while(p!=NULL) . ,空类型指针: void *指针变量名 表示:void *p; 使用时要进行强制类型转换,例 char *p1; void *p2; p1=(char *)p2;,表示不指定p是指向哪一种 类型数据的指针变量,例:指针的概念,main() int a; int *pa= ,运行结果: a:10 *pa:10 scanf(%d,%d,

5、 ,运行结果:a=5,b=9 max=9,min=5,5,2006,9,2008,2006,2008,2006,指针变量作为函数参数,swap(int x,int y) int temp; temp=x; x=y; y=temp; main() int a,b; scanf(%d,%d, ,例:将数从大到小输出,5,9,5,5,9,COPY,值传递,运行结果:5, 9,swap(int *p1, int *p2) int t; t=*p1; *p1=*p2; *p2=t; main() int a,b; int *pointer_1,*pointer_2; scanf(%d,%d, ,5,9,

6、2000,2002,5,9,COPY,5,例:将数从大到小输出,地址传递,运行结果:9,5,swap(int *p1, int *p2) int *p; *p=*p1; *p1=*p2; *p2=*p; main() int a,b; int *pointer_1,*pointer_2; scanf(%d,%d, ,运行结果:9,9,int x; int *p=,例:将数从大到小输出,5,9,2000,2002,9,9,COPY,假设2000,指针变量在使用前 必须赋值!,编译警告! 结果不对!,swap(int x,int y) int t; t=x; x=y; y=t; main() in

7、t a,b; int *pointer_1,*pointer_2; scanf(%d,%d, ,运行结果:5,9,例:将数从大到小输出,值传递,5,9,2000,2002,COPY,5,5,9,运行结果:5,9,例:将数从大到小输出,swap(int *p1, int *p2) int *p; p=p1; p1=p2; p2=p; main() int a,b; int *pointer_1,*pointer_2; scanf(%d,%d, ,5,9,2000,2002,COPY,2000,2000,2002,不可能改变实参指针变量的值,9.3 指针与数组,指向数组元素的指针变量,例 int

8、array10; int *p; p=,数组名是表示数组首地址的地址常量,指针的运算 指针变量的赋值运算 p= (指针变量p2值p1) 不能把一个整数p,也不能把p的值整型变量,如 int i, *p; p=1000; () i=p; (),指针的算术运算: pi p id (i为整型数,d为p指向的变量所占字节数) p+, p-, p+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;

9、 int *p=,例 int a10; int *p1=,1,指针变量的关系运算 若p1和p2指向同一数组,则 p1p2 表示p1指的元素在后 p1=p2 表示p1与p2指向同一元素 若p1与p2不指向同一数组,比较无意义 p=NULL 或 p!=NULL,注意: *p+ 等价于 *(p+),先得到*p的值,再做p+ *p- 等价于 *(p-) , 先得到*p的值,再做p-; *(+p) p先自增1,再得到*p的值 *(-p) p先自减1,再得到*p的值; (*p)+ 使元素值加1,(*p)- 使元素值减1。,数组元素表示方法, 变址运算符 ai *(a+i),ai pi *(p+i) *(a

10、+i),例:数组元素的引用方法,main() int a5,*pa,i; for(i=0;i5;i+) ai=i+1; pa=a; for(i=0;i5;i+) printf(*(pa+%d):%dn,i,*(pa+i); for(i=0;i5;i+) printf(*(a+%d):%dn,i,*(a+i); for(i=0;i5;i+) printf(pa%d:%dn,i,pai); for(i=0;i5;i+) printf(a%d:%dn,i,ai); ,例:int a=1,2,3,4,5,6,7,8,9,10, *p=a, i; 数组元素地址的正确表示: (A) /*含义为:*p=*q

11、; p+; q+; */,main() int a =5,8,7,6,2,7,3; int y, *p= ,输出:5 6,例:指针变量的运算,6,main() int i, *p, a7; p=a; for(i=0;i7;i+) scanf(%d,p+); printf(n); for(i=0;i7;i+,p+) printf(%d,*p); ,例:注意指针的当前值,p=a;,指针变量可以指到数组后的内存单元,数组名作函数参数 数组名作函数参数,是地址传递 数组名作函数参数,实参与形参的对应关系,例:将数组a中的n个整数按相反顺序存放,实参与形参均用数组,void inv(int x, int

12、 n) int t, i, j, m=(n-1)/2; for(i=0; i=m; i+) j= n-1-i; t=xi; xi=xj; xj=t; main() int i, a10=3,7,9,11,0,6,7,5,4,2; inv(a,10); printf(The array has been reverted:n); for(i=0; i10; i+) printf(%d, ai); printf(n); ,m=4,例:将数组a中的n个整数按相反顺序存放,void inv(int *x, int n) int t, *p, *i, *j, m=(n-1)/2; i=x; j=x+n-

13、1; p=x+m; for( ; i=p; i+, j-) t=*i; *i=*j; *j=t; main() int i, a10=3,7,9,11,0,6,7,5,4,2; inv(a,10); printf(The array has been reverted:n); for(i=0;i10;i+) printf(%d, ai); printf(n); ,实参用数组,形参用指针变量,例:将数组a中的n个整数按相反顺序存放,void inv(int *x, int n) int t, *i, *j, *p, m=(n-1)/2; i=x; j=x+n-1; p=x+m; for( ; i

14、=p; i+, j-) t=*i; *i=*j; *j=t; main() int i,a10,*p=a; for(i=0; i10; i+, p+) scanf(%d, p); p=a; inv(p,10); printf(The array has been reverted:n); for(p=a; pa+10; p+) printf(%d,*p); ,实参与形参均用指针变量,例:将数组a中的n个整数按相反顺序存放,void inv(int x, int n) int t, i, j, m=(n-1)/2; for(i=0; i=m; i+) j=n-1-i; t=xi; xi=xj;

15、xj=t; main() int i, a10, *p=a; for(i=0; i10; i+,p+) scanf(%d, p); p=a; inv(p,10); printf(The array has been reverted:n); for(p=a; pa+10; p+) printf(%d ,*p); ,实参用指针变量,形参用数组,总结:指针变量与一维数组的关系 int *p 与 int q10 数组名是指针(地址)常量 p=q; p+i 是qi的地址 数组元素的表示方法:下标法和指针法,即若p=q, 则 pi qi *(p+i) *(q+i) 形参数组实质上是指针变量,即int q

16、 int *q 在定义指针变量(不是形参)时, 不能把 int *p; 写成 int p; 系统只给p分配能保存一个指针值的内存区(一般24字节);而给q分配2*10字节的内存区,指针与二维数组 二维数组的地址,对于一维数组: (1)数组名array表示数组的首地址, 即array0的地址; (2)数组名array是地址常量 (3)array+i是元素arrayi的地址 (4)arrayi *(array+i),对于二维数组: (1)a是数组名, 包含三个元素 a0,a1,a2 (2)每个元素ai 又是一个一维 数组,包含4个 元素,int a34;,基类型,对二维数组 int a34,有 a

17、-二维数组的首地址,即第0行的首地址 a+i-第i 行的首地址 ai *(a+i)-第i行第0列的元素地址 ai+j *(a+i)+j -第i行第j列的元素地址 *(ai+j) *(*(a+i)+j) aij,a+i= int *p; for(p=a0;pa0+12;p+) if(p-a0)%4=0) printf(n); printf(%4d ,*p); ,指向一维数组的指针变量 定义形式: 数据类型 (*指针名)一维数组维数; 例 int (*p)4;,( )不能少 int (*p)4与int *p4不同,p的值是一维数组的 首地址,p是行指针,可让p指向二维数组某一行 如 int a34

18、, (*p)4=a;,一维数组指针变量维数和 二维数组列数必须相同,例:指向一维数组的指针变量举例,main() static int a34=1,3,5,7,9,11,13,15,17,19,21,23; int i, j, (*p)4; for( p=a, i=0; iy) return ,main() int a=2,b=3; int *p; p=f3(a, b); printf(%dn,*p); ,2,3,3,2,*,例:写一个函数,求两个整型变量中较大者的地址,200A,不应将形参或局部变量 的地址作函数返回值,例:在输入的字符串中查找一个给定的字符,如果找到输出从该字符开始的剩余字

19、符串,否则输出没找到。,#include char *match(char ch, char * str) while(ch!=*str ,内存动态申请和释放,void * malloc(unsigned int size) 在动态存储区分配长度为size的连续空间,并返回指向该空间起始地址的指针。若分配失败(系统不能提供所需内存),则返回空指针(NULL)。 例:int *p=(int *)malloc(sizeof(int)*length); void free(void * ptr) 释放ptr指向的内存空间。ptr是malloc()函数返回的值。 例:free(p);,函数指针:函数在

20、编译时被分配的入口地址,函数指针变量用函数名赋值:如 p=max;,专门存放函数入口地址 可指向返回值类型相同的不同函数,函数返回值的数据类型,指向函数的指针变量 定义形式:数据类型 (*指针变量名)() 如 int (*p)( );,函数指针变量指向的函数必须有函数声明,函数调用形式: c=max(a,b); c=(*p)(a,b); c=p(a,b); 对函数指针变量pn, p+, p-无意义,( )不能省 int (*p)() 与 int *p()不同,例:用函数指针变量调用函数,比较两个数大小,main() int max(int ,int); int a,b,c; scanf(%d,

21、%d, ,main() int max(int, int); int (*p)(); int a,b,c; p=max; scanf(%d,%d, ,用函数指针变量作函数参数,例:用函数指针变量作参数,求最大值、最小值和两数之和,9.6 指针数组,指针数组 定义:数组中的元素为指针变量 定义形式:存储类型 数据类型 *数组名数组长度;,指针所指向变量的数据类型,指针本身的存储类型,注意:区分int *p4与int (*p)4,例:int *p4;,指针数组赋值与初始化,char name59=“gain”,“much”,“stronger”, “point”,“bye”;,char *name

22、5=“gain”,“much”,“stronger”, “point”,“bye”;,二维数组与指针数组区别:,二维数组存储空间固定 字符指针数组相当于可变列长的二维数组 分配内存单元=数组维数*2+各字符串长度,指针数组元素的作用相当于二维数组的行名 但指针数组中元素是指针变量 二维数组的行名是地址常量,例:对字符串排序(简单选择排序),main() void sort(char *name,int n), print(char *name,int n); char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; int n=5; s

23、ort(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; ,i=0,main() void sort(char *name,int n), print(char *name,int n); char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; int n=5; sort(name,n); print(name,

24、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; ,name0,name1,name2,name3,name4,name,Great Wall,FORTRAN,Computer,Follow me,BASIC,i=1,例:对字符串排序(简单选择排序),main() void sort(char *name,int n), print(char *name,int n); char *name=Follow me

25、,BASIC, Great Wall,FORTRAN,Computer ; 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; ,name0,name1,name2,name3,name4,name,Great Wall,FORTRAN,Computer,Follow me,BASIC,i=2,例:对字符串排序(简单选择排序),main() vo

26、id sort(char *name,int n), print(char *name,int n); char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; 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; ,name0,name1,name2,name3,name4,name,Gr

27、eat Wall,FORTRAN,Computer,Follow me,BASIC,i=3,例:对字符串排序(简单选择排序),main() void sort(char *name,int n), print(char *name,int n); char *name=Follow me,BASIC, Great Wall,FORTRAN,Computer ; 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) tem

28、p=namei; namei=namek; namek=temp; ,name0,name1,name2,name3,name4,name,Great Wall,FORTRAN,Computer,Follow me,BASIC,例:对字符串排序(简单选择排序),一级指针:指针变量中存放目标变量的地址,例 int *p1; int *p2; int i=3; p2=,二级指针:指针变量中存放一级指针变量的地址,例 int *p; int i=3; p=,一级指针,单级间接寻址,二级指针,一级指针,目标变量,二级间接寻址,9.7 多级指针指向指针的指针,二级指针定义形式:存储类型 数据类型 *指针

29、名;,指针本身的存储类型,最终目标变量的数据类型,例 int i=3; int *p1; int *p2; p1=,5,多级指针 例:三级指针 int *p; 四级指针 char *p;,例:int i, *p; p= () /*p是二级指针,不能用变量地址为其赋值*/,例:用二级指针处理字符串,#define NULL 0 void main() char *p; char *name=hello,good,world,bye,; p=name+1; printf(%o : %s , *p,*p); p+=2; while(*p!=NULL) printf(%sn,*p+); ,运行结果:

30、644 : good bye,用*p可输出地址(%o或%x), 也可用它输出字符串(%s),int *p 与 int *q10 指针数组名是二级指针常量 若p=q; p+i 是qi的地址; 指针数组作形参时,int *q 与int *p完全等价; 但作为变量定义两者不同: 系统只给p分配能保存一个指针值的内存区; 而给q分配10块内存区,每块可保存一个指针值。,二级指针与指针数组的关系,命令行参数 命令行一般形式:命令名 参数1 参数2参数n,main(int argc, char *argv) ,命令行参数的传递,带参数的main函数形式:,例:C:TC copy.exe source.c

31、temp.c,有3个字符串参数的命令行,命令行中参数个数,元素指向命令行参数 中各字符串首地址,形参名任意,第一个参数: main所在的可执行文件名,例:输出命令行参数,main(int argc, char *argv) while(argc1) +argv; printf(%sn,*argv); -argc; ,1. 编译、链接test.c,生成可执行文件test.exe 2. 在DOS状态下运行(test.exe所在路径下),例如: C:TC test.exe hello world!,运行结果:hello world!,指针的数据类型小结,例:下列定义的含义 (1)int *p3; (

32、2)int (*p)3; (3)int *p(int); (4)int (*p)(int); (5)int *(*p)(int); (6)int (*p3)(int); (7)int *(*p3)(int);,指针运算小结,取地址运算符&:求变量的地址;取内容运算符*:指针所指的变量。 赋值运算: 把变量地址赋予指针变量 同类型指针变量相互赋值 把数组,字符串的首地址赋予指针变量 把函数入口地址赋予指针变量 加减运算: 对指向数组,字符串的指针变量可以进行加减运算,如p+n,p-n,p+,p-等。对指向同一数组的两个指针变量可以相减。对指向其它类型的指针变量作加减运算是无意义的。 关系运算: 指向同一数组的两个指针变量之间可以进行大于、小于、 等于比较运算。指针可与0比较,p=0表示p为空指针。,

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

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!