《c语言指针课件PPT课件.ppt》由会员分享,可在线阅读,更多相关《c语言指针课件PPT课件.ppt(81页珍藏版)》请在人人文库网上搜索。
1、第9章 指 针,1,特 点,能直接对内存地址操作, 使用灵活,实现动态存储管理,可以使程序简洁、紧凑、高效,用间接访问的方式改变数据的逻辑顺序,调用函数时可实现变量的引用传递,2,地址和指针的概念,变量的地址和变量的值,int i=3; float j=6; double k=9;,3,6.0,9.0,变量i,变量j,变量k,2200,2206,2202,2214,程序中定义的变量, 系统根据它的 类型给它分配一定长度的内存单元, 该内存单元的起始地址即为变量的地址。,该内存单元的内容就是变量的值。,3,直接访问和间接访问,直接访问:,用变量名直接从它对应的地址存取内容。,如: int x=5。
2、,y=8,z=0; z =x+y;,13,直接从 x 和 y 对应的地址2200和2202 取出内容5和8然后相加将结果13存入 变量 z 对应的地址2204的单元中。,4,间接访问,定义一个存放地址的变量p (p的地址1500), 将x的地址 2200存放在变量 p 中。通过 变量p取出地址2200, 再按此 地址存取其中的内容, 就间接 的完成了对x的存取。,当p的内容改为2202时, 通过 变量p取出地址2202, 再按此 地址, 存取的就是变量y的内 容。,p就是指针变量,5,8,0,变量x,变量y,变量z,2200,2202,2204,2202,5,指针变量的定义,一般形式:,基类型。
3、名 *指针变量名,说明:,基类型名: 指针变量所指向的变量的类型名称,指针变量名: 所定义的指针变量的名称,*: 表示它后面的变量名是指针类型,功能:,(1)定义该指针变量名为指向基类型的指针变量,为 该变量分配存储单元, 其长度等于存储地址的字节数。,(2) 基类型确定用指针变量“间接”存取数据的存储单 元个数和存储形式。该变量只能指向基类型数据。,6,指针变量的初始化,用 = float *p=,可以用赋值语句给指针变量赋值:,float y, *py; py=,7,指针变量的引用,引用指针变量的指针值与引用其它 类型的变量一样直接用它的变量名,引用指针变量所指向的变量时, 用“*指针变量。
4、名”,注意: 指针变量的值与它所指向变量的值之间的差别,指针变量只有正确赋值后才能通过它访问指向的变量。,int x;,p=,int *p;,*p,*p=5;,5,8,指针变量的运算,1. ,11,给变量赋值的两种方法,1. 直接访问用变量名,如: int i; i=5;,2. 间接访问通过指向变量i的地址的指针变量 p 赋值,如:int i, *p; p=,12,取地址运算符 int *p= ,运行结果: Input m,n: 123 456 m=123 ,main( ),运行结果: min=6, max=8,例:通过交换指针变量值按大小顺序输出,14,指针变量作为函数的参数,以指针类型为函。
5、数的参数,作用是将变量的地址传入函数。,15,int x,y; int *pt1;*pt2;,x=8;y=6;,pt1=,if (xy) swap(pt1,pt2);,printf(x=%d, y=%dn,x,y);,swap(int *p1,int *p2),p=*p1;,*p1=*p2;,*p2=p;, int p;,8, main() ,6,8,运行结果: x=6, y=8,int x,y; int *pt1;*pt2;,x=8;y=6;,pt1=,if (xy) swap(pt1,pt2);,swap(int *p1,int *p2),p=*p1;,*p1=*p2;,*p2=p;, i。
6、nt p;,printf(x=%d, y=%dn,x,y);,16,指针与数组,C语言中规定数组名是指针类型的符号常量, 该符号常量值等于数组首元素的地址 ( 简称数 组首地址) ,它的类型是指向数组元素的指针类型。 即数组名是指向该数组首元素的指针常量。,17,指向数组元素的指针,1.定义指向数组元素的指针变量,定义指向数组元素的指针变量与定义指向变量的指针变量的 方法相同.如:,int a10; int *p; p=,由于数组名是指向0号元素的指针类型符号常量, 所以a与 p=a; p+; p+=3;,19,注意: 指针变量的运算顺序。,+*p,*p+,*(+p),(*p)+ 四者之间的差。
7、别:,+*p,先给p指向的变量加1,然后取其值,(*p)+,先取p指向的变量值, 然后该变量值加1,*p+,取p所指向变量的值, 然后p增1,*+p,P先增1, 然后取p所指向变量的值,20,main() int a4=1,2,3,4,b,c,d,e; int *p=a; b=*p+; printf(“n%d,%d,”,b,*p); c=*+p; d=+*p; printf(“%d,%d”,c,d); ,运行结果 1,2,3,4,21,通过指针引用数组元素,在 int a10,*p=a; 定义的情况下:,(1) p+i或a+i就是ai的地址。都要进行a+id的运算。,(2) *(p+i)或*(。
8、a+i)就是p+i或a+i所指向的数组元素ai。 数组元素中的 “ ” 是变址运算符, 相当于*( + ) , ai 相当于*(a+i)。,(3) 指向数组元素的指针变量也可带下标, 如 pi与*(p+i)等价。 所以, ai,*(a+i) ,pi,*(p+i) 四种表示法全部等价。,(4) 注意p与a的差别,p是变量a是符号常量,不能给a赋值, 语句a=p; a+; 都是错的。,22,a,引用数组元素可用: 1)下标法,如ai,pi。 2) 指针法,如*(p+i)或*(a+i),其中p是指向数组a的元素的指针变量。,23,main( ) int a10; int *p,i; for(p=a;。
9、p0) printf(%s%c,*+argv,(argc1)? :n); ,在操作系统命令行状态下输入: echo Welcome to you ! ,执行后输出以下信息: Welcome to you !,56,【例9.18】实现系统提供的字符串复制函数strcpy()的全部功能。,char *strcpy(char *s1,char *s2) char *p=s1; while(*s1+=*s2+); return(p); main() char s20; printf(%sn,strcpy(s,Welcome to you!); ,57,结构体与指针,指向结构体变量的指针,结构体指针变量。
10、的定义: struct 结构体名 * 指针变量名; 例如: struct student *pt=,struct student int num; char name20; char sex; int age; stu;,58,使用结构体指针变量引用成员形式,(*结构体指针名).成员名,结构体指针名-成员名,结构体变量名.成员名,struct student int num; char name20; char sex; int age; stu; struct student *p=,(*p).num,p-num,stu.num,p= char name20; char sex; int a。
11、ge; ; main() struct student stu, *p; p= ,60,例:结构体数组指针的使用,struct student int num; char name20; char sex; int age; stu3= 10101, Li Lin,M,18, 10102,Zhang Fun,M,19, 10103,Wang Min,F,20; main() struct student *p; for(p=stu;pnum,p-name, p-sex,p-age); ,10101,Li Lin,M,18,10102,Zhang Fun,M,19,10103,Wang Min,。
12、F,20,61,结构体指针作函数参数,用结构体变量的成员作参数-单值传递 用结构体变量作参数-多值传递 用指向结构体变量或数组的指针作参数 -地址传递。,62,【例9.17】 采用“引用传递”的方式,用指向结构体 的指针变量作参数,在input函数中输入并计算平均成 绩,在main函数输出。,#define N 4 #include #define FMT %5d %-11s%5d%8d%8d%10.1fn struct st int num; char name11; int s3; float aver; ; void input(struct st *p) scanf(%d%s%d%d%。
13、d, ,63,指针与链表,链表可以动态的进行存储分配,head: 头指针,存放一个地址,指向链表中的第一个元素.,每一个元素称为一个“结点”,每个结点都包括两部分:,1.用户需要的实际数据;,2.下一个结点的地址.,表尾: 它的地址部分放一个“NULL”,链表到此结束.,64,可用结构体类型的变量来存储链表中的结点元素.,每一个结点中存放地址的部分可用指针来实现.,例: struct student int num; float score; struct student *next; ;,65,简单静态链表,# define NULL 0 struct student long num; f。
14、loat score; struct student *next; ; main( ) struct student a,b,c,*head,*p; a.num=9901; a.score=89.5; b.num=9903; b.score=90; c.num=9905; c.score=85; head= ,9901,89.5,9903,90,9905,85,作用是: 在内存的动态存储区分配一个长度为size的连续空间,原型说明在“stdlib.h”头文件和“alloc.h”头文件中,67,2.calloc函数,void *calloc(unsigned n,unsigned size);,。
15、作用是: 在内存的动态区分配n个长度为size的连续空间.,3. free函数,void free(void *p);,作用是: 释放由p指向的内存区.,68,typedef struct Node int data; struct Node *next; Node;,链表的插入操作,s-next=pre-next;,pre-next=s;,顺序可以 颠倒吗?,void InsList(Node *L,int i,int e) Node *pre,*s; int k=0; pre=L; while(pre!=NULL ,69,链表的删除操作,pre-next=pre-next-next;,fr。
16、ee(r);,void DelList(Node *L,int i) Node *pre,*r; pre=L; int k =0; while(pre-next!=NULL ,70,建立动态链表,头插法建表,尾插法建表,头插法建表,s指向新申请的结点 s-data=A;,插入第一个结点:,插入某一个结点:,s-next=H-next;,H-next=s;,顺序可以 颠倒吗?,71,Linklist CreateFromHead( ) Node *s,*L; char c; int flag=1; L=(Node*)malloc(sizeof(Node); L-next=NULL; while(。
17、flag) c=getchar(); if(c!=$) s=(Node*)malloc(sizeof(Node); s-data=c; s-next=L-next; L-next=s; else flag=0; ,72,尾插法建表,s指向新申请的结点 s-data=A;,插入第一个结点:,插入某一个结点:,r-next=s;,r=s;,顺序可以 颠倒吗?,73,Linklist CreateFromTail() Node *L,*r, *s; int flag =1; L=(Node * )malloc(sizeof(Node); L-next=NULL; r=L; while(flag) c。
18、=getchar(); if(c!=$) s=(Node*)malloc(sizeof(Node); s-data=c; r-next=s; r=s; else flag=0; r-next=NULL; ,74,指针与函数,返回值为指针类型的函数,指针函数的定义格式如下: 类型名 *函数名(参数表),例如:int *f(int x),75,指向函数的指针,指针变量的另一的重要用途是, 它可以指向一个函数 (存储函数入口地址), 通过它可以调用指向的函数, 改 变它的值就可以动态的调用不同的函数。,指向函数的指针和函数参数,76,指向函数的指针的定义,一般形式:,数据类型 (* 指针变量名)( 。
19、),例如: int (*p)( );,说明:,1.在给函数指针变量赋值时,只需给出函数名而不必给参数;,2.用函数指针调用函数时,只需用*p代替函数名即可.,77,【例9.20】 指向函数的指针程序举例。 #include int f(int x) return 3*x*x+5*x-7; void main() int (*p)(); int a; p=f; printf(Input x=); scanf(%d, ,78,作 业,1. #include main( ) int a23=1,2,3,4,5,6; int m,*p; p= ,79,2. #include main( ) char a =“language”,b =“program”; char *p=a,*q=b; int k; for(k=0;k7;k+) if(*(p+k)=*(q+k) printf(“%c”,*(p+k); ,80,3. main( ) char a =“Basic”; char *p; for(p=a;pa+5;p+) printf(“%sn”,p); ,P195. 9.1, 9.8, 9.12,81。