C语言PPT课件第08章 指针.ppt_第1页
C语言PPT课件第08章 指针.ppt_第2页
C语言PPT课件第08章 指针.ppt_第3页
C语言PPT课件第08章 指针.ppt_第4页
C语言PPT课件第08章 指针.ppt_第5页
已阅读5页,还剩60页未读 继续免费阅读

下载本文档

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

文档简介

,指 针,共 20页 第 2 页,第7章 指针,第一节 地址和指针的概念 第二节 变量的指针和指针变量 第三节 数组指针 第四节 字符串指针 第五节 函数指针 第六节 返回指针的值 第七节 指针数组 第八节 小结,共 20页 第 3 页,第7章 指针,指针是C语言中的一个重要的概念,正确而灵活地运用它,可以有效地表达复杂的数据结构;能动态分配内存;能方便地使用字符串、数组、函数;能直接处理内存地址。 可以说,不掌握指针就不掌握C语言。,共 20页 第 4 页,两个概念 内存单元: 程序中定义的每个变量,都在内存中占有一定的空间,称为内存单元。 内存单元地址: 内存区的每一个字节有一个编号,称为内存地址。,7-1地址和指针的概念,共 20页 第 5 页,例如程序定义了三个变量: Int a,b,c; 则系统给出三个单元: 地址1 地址2 地址3,7-1地址和指针的概念,共 20页 第 6 页,实际上一个变量有三个值:地址、变量名、值。例: Int a=3,b=7,c=9; 地址 变量名 值 地址1 地址2 地址3,7-1地址和指针的概念,共 20页 第 7 页,内存单元的大小: 程序中不同类型的变量,大小也不一样。 *实型变量:占有 4 个字节。 *整型变量:占有 2 个字节。 *字符变量:占有 1 个字节。 注:1个字节为8位:,7-1地址和指针的概念,7 6 5 4 3 2 1 0,共 20页 第 8 页,例:程序定义了3个整型 内存用户数据区 变量i、j、k,编译时系统 分配置2000和2001两个字 节给变量i,2002和2003字 2000 3 变量i 节给j,2004,20005给k。 2002 6 变量j 则有:变量 开始地址 2004 9 变量k i 2000 . j 2002 . k 2004 3010 2000 i-pot 单元内的内容就是变量的值,7-1地址和指针的概念,共 20页 第 9 页,对变量的存取是通过地址 内存用户数据区 来进行。如果语句中有: “k=i+j”,则从2000、2001 字节取出I值(3),再从 2000 3 变量i 2002,2003字节取出j值 2002 6 变量j (6),相加后得(9), 2004 9 变量k 送给k所占的2004, . 2005单元。 . 这种存取方式称为 3010 2000 i-pot “直接访问:方式。,7-1直接访问方式,共 20页 第 10 页,也可以采用另一种存取方式, 内存用户数据区 变量I的地址存放在另一个变量 Ipot中,即:Ipot= 这样,Ipot的值就是2000, 2000 3 变量i 即变量I的起始地址。要存 2002 6 变量j 取I的值,也可以从变量 2004 9 变量k Ipot中取出I的地址(2000) . 然后到2000,2001处取出 . I的值(3)。 3010 2000 ipot 这种存取方式称为 : “间接访问:方式,7-1间接访问方式,共 20页 第 11 页,7-2地址和指针的概念,*什么叫做指针? 举两个日常例子: (1)每个同学的记分表都有这三栏: 编 号 姓 名 分数 1001 王 刚 70 1002 李 鹏 78 1003 张 三 92 那么,要对某个同学记分和查分都是通过编号进行,编号就是姓名的指针。,共 20页 第 12 页,指针: 由于通过地址能找到所需的变量单元,我们称一个变量的地址为该变量的指针。 地址1(指针1) 地址2(指针2) 地址3(指针3),7-1地址和指针的概念,共 20页 第 13 页,指针变量: 一个变量,是用来存放另一个变量的地址,则它称为指针变量。,地址和指针的概念,共 20页 第 14 页,指针变量的定义格式 基本类型 *指针变量名 例: float *p1; /*实型指针*/ int *p2; /*整型指针*/ char *p3; /*字符指针*/ 注意 “*”号 不能省略。,7-2-1定义一个指针变量,共 20页 第 15 页,例:通过指针变量的赋值。必须在变量面前加上地址赋值符号:“ /*变量c的地址赋给指针p3*/,7-2-2指针变量的引用,共 20页 第 16 页,指针变量的使用。如果有: int a,*p1; a=100; p1=,7-2-2指针变量的引用,共 20页 第 17 页,同样有: Float b,*p2; b=3.12; p2=,7-2-2指针变量的引用,共 20页 第 18 页,因此,只要有: Float b,d,*p2; p2=,7-2-2指针变量的引用,共 20页 第 19 页,例:通过指针变量访问整形变量。 Main() int a,b,*p1,*p2; a=100;b=10; p1= 结果为: 100,10 100,10,7-2-2指针变量的引用,共 20页 第 20 页,注意: (1)指针变量前面的“*”, 表示该变量的类型为指针 型变量。 (2)在定义指针变量时必 须指定基本类型 原因是:单位字节数不同。 实型指针变量一个单位是 4个字节。 型型指针变量一个单位是 2个字节。 字符型指针变量一个单位是 1个字节。 指针变量的赋值 point-2= /*字符变量a的地址赋给指针*/,7-2-1定义一个指针变量,2000 2001 2002 2003 2004 2005 2006,实变 量f,型变 量i,字符a,共 20页 第 21 页,例:输入a,b两个整数,按先大后小输出a和b。 Main() int a,b,*p1,*p2; Scanf(“%d,%d”, 输入 5,9 结果为: a=5,b=9 max=9,mix=5,7-2-2指针变量的引用,共 20页 第 22 页,当输入a=5,b=9时,由于ab,将p1和p2交换。 如图: 注意:a和b并未交换,但p1和p2的值改变了。P1的为&a,现为&b,p2原为&b,现为&a。,7-2-2指针变量的引用,p,&b,&a,p2,a,p1,p,9,b,5,b,a,p2,p1,9,&a,&b,共 20页 第 23 页,函数的参数不仅可以是整型、实型、 字符型等,还可以是指针型。 指针变量作为函数参数的作用是: 将一个变量的地址传送到另一个函数中。 再举上例:输入a,b两个整数,按先大后小输出a和b。,7-2-3指针变量作为函数参数,共 20页 第 24 页,main() int a,b,*t1,*t2; scanf(“%d,%d”,7-2-3指针变量作为函数参数,共 20页 第 25 页,子函数 sw 的作用是交换两个变量a和b的值。 Sw(int *p1,int *p2) int temp; temp=*p1; *p1=*p2; *p2=temp; 运行情况如下: 输入: 5,9 结果: 9,5,7-2-3指针变量作为函数参数,共 20页 第 26 页,当t1=&a,t2=&b时 当调用sw(t1,t2)时 如图:,7-2-3指针变量的引用,&b,&a,p2,a,p1,9,b,5,b,a,p2,p1,9,&a,&b,&b,&a,t1,t2,共 20页 第 27 页,当执行函数sw(t1,t2)时 当返回主函数时,7-2-3指针变量的引用,&b,&a,t2,a,t1,9,b,5,b,a,p2,p1,9,&a,&b,&b,&a,t1,t2,5,函数调用结束后,p1和p2不复存 在(已释放),共 20页 第 28 页,数组与指针的关系 每一个数组元素都有地址。该地址就是数组元素的指针。 概念 假设:int a100; 数组名:数组的标识 a 数组元素的地址:数组中一个具体元素的地址(&ak) 数组首地址(数组起始地址):数组中第一个元素(0号元素)的地址(&a0或用数组的名称 a 表示)。,7-3数组与指针,共 20页 第 29 页,C语言规定:数组名就是数组的首地址常量。 那么下面关系表达式成立:a = 将第一个元素的地址赋给p, 实际上是首地址赋给p。 与下条语句等价: p=a p就称为指向数组a的指针变量。,指向数组的指针,&a0,a0,共 20页 第 30 页,C语言规定:如果指针变量p已指向数组中的一个元素, 则p+1指向同一数组中的下一个元素。 例如: int a4,*p; p= 则: p+1 a1 p+2 a2 p+3 a3,7-3指向数组的指针,注:这里的p+1是指加上一个单元, 不同的变量,单元的大小不同。 整型指针变量p+1等于p的地址 加上2个字节。 p+2=p+4个节。 (实型: p+1=p+4个字节。 字符型: p+1=p+1个字节。,共 20页 第 31 页,例C5_5001.C:分析程序。 #include main ( ) int a = 1, 2, 3, 4, 5 ; int x, y, *p; /* 指针变量 p */ p= ,7-3数组与指针,例C5_5001,/* 指针 p 指向 a0,等价于p=a */,/* 取指针p+2的内容,等价于x=a2 */,/* 取指针p+4的内容,等价于y=a4 */,共 20页 第 32 页,例C5_5002.C:分析程序。 main( ) int a = 1, 2, 3, 4, 5, 6 ; int *p; p=a; /* 指针p为数组的首地址 */ printf (“%d“, *p ); printf (“ %dn“, *(+p) ); printf (“%d“, *+p ); printf (“ %dn“, *(p-) ); p += 3; printf(“%d %dn“, *p, *(a+3) ); ,7-3 数组与指针,例C5_5002,指针初始化,第一个输出,第二个输出,第三个输出,第四个输出,第五个输出,p=a,取p的内容,p先加1再取内容,p先加1再取内容,取内容p再减1,取p的内容,p+=3,p,p,p,p,p,p,语句执行,指针p指向,地址,数组,共 20页 第 33 页,在函数之间传递整个数组 实际参数用数组名。 形式参数用指针时,在被调用函数的内部,就可用指针方式访问数组中的元素。 说明 由于数组名代表数组的首地址,传递数组名也就是将数组的首地址传递给被调用函数。,7-3-3 数组名作为函数,共 20页 第 34 页,例:编写字符串复制函数。 main( ) char a30, b30; printf(“Enter string:“); scanf (“%s“, a); strcopy ( a, b ); /* 调用函数的实参为数组名 */ printf (“a=%snb=%sn“, a, b ); strcopy ( str1, str2 ) /* 将串str1拷贝到串str2中 */ char * str1, * str2; /* 形参为指向字符的指针 */ while ( (*str2 = *str1)!=0) /* 通过指针操作数组 */ str1+; str2+; 5-5 数组与指针-串复制,7-3 数组与指针-串复制,例C5_5003,共 20页 第 35 页,例:改进字符串复制函数。 改进一: strcopy ( str1, str2 ) char *str1, *str2; while ( *str2 = *str1 ) str1+; str2+; 改进二: strcopy ( str1, str2 ) char *str1, *str2; while ( *str2+ = *str1+ ) ; /* 通过指针操作数组 */ ,7-3数组与指针-串复制,例C5_50031,例C5_50032,共 20页 第 36 页,对于指针的三种基本运算 指针与正整数的加减运算 两个指针的关系运算 两个指针的减法运算 与指针相关的运算操作 取地址运算 ( & ) 取内容运算 ( * ),7-3指针的基本运算,共 20页 第 37 页,指针与正整数的加减法 当指针 p 指向数组中的元素时,n为正整数: p+n表示:指针p所指向当前元素之后的第n个元素; p-n表示:指针p所指向当前元素之前的第n个元素。 p+和+p含义:指针加1,指向数组中的下一个元素; p-和-p含义:指针减1,指向数组中的前一个元素。,7-3 指针的基本运算-指针加减运算,p-2,p-1,p,p+1,p+2,p-3,共 20页 第 38 页,设 int b,c,d,e,a4; p= 相当于 e=+a0, 先取a0=a0+1 等于4,后 赋给d。,7-3指针的基本运算,共 20页 第 39 页,回忆! 对于一个字符串,我们是如何访问? 方法:用字符数组。 例: main() int I; char st6=“china”; for ( I=0;I=5;I+) printf(“%c”,aI); 结果输出:china,7-4字符串的指针和指向字符串的的指针变量,共 20页 第 40 页,也可以用字符指针来访问一个字符串。 例: main() char *sp 定义指针变量 sp=“china”; 表示将字符串 printf(“%sn”,sp; “china”的首 结果输出:china 地址赋给sp,7-4字符串的指针和指向字符串的的指针变量,共 20页 第 41 页,例:将字符串a复制为字符串b。 main() int j; char a=“china”,b5,*p,*q; p=a; for (j=0;j=5;j+) *(q+j)=*(p+j); 指针改变数组b的值 printf(“n%s”,p); for(j=0;j=5;j+) printf(“n%c”,bj); 结果: china china,7-4字符串的指针和指向字符串的的指针变量,共 20页 第 42 页,上例也可改为: main() int j; char a=“china”,b5; for (j=0;j=5;j+) *(b+j)=*(a+j); 指针改变数组b的值 printf(“n%s”,a); for(j=0;j=5;j+) printf(“n%c”,bj); 结果: china china,7-4字符串的指针和指向字符串的的指针变量,共 20页 第 43 页,前面介绍过,字符数组和字符指针都能实现字符串的存储和运算。但它们两者是有区别 (1)字符数组由若干个元素组成,每个元素放一个字符。 字符指针变量中存放的是地址-字符串的首地址。而不是将字符串放到字符指针变量中,7-4-3对使用字符指针变量和字符数组的区别,共 20页 第 44 页,(2)赋值方式。对字符数组只能对各个元素赋值,不能如下赋值: Char st5; St=“china”; 而字符指针变量中,可以这样做: Char *sp sp=“china”; 注意:sp存放的是字符串的首地址。,7-4-3对使用字符指针变量和字符数组的区别,共 20页 第 45 页,例C5_5004.C:使用指针作为形式参数实现函数day_of_year。 #include main( ) static int day_tab213 = 0,31,28,31,30,31,30,31,31,30,31,30,31, 0,31,29,31,30,31,30,31,31,30,31,30,31 ; int y, m, d; scanf(“%d%d%d“, ,7-4 数组与指针-用指针操作二维数组,例C5_5004,共 20页 第 46 页,指针数组 数组中的元素均为指针类型,称之为指针数组。 指针数组说明的形式为: 数据类型 * 数组名常量表达式 例如: int * pa 6; 含义:定义一个由6个指针变量构成的指针数组,数组中的每个数组元素指针,都指向一个整数。,7-5 指针数组,共 20页 第 47 页,数组指针 指向数组的指针称为数组指针。 数组指针的说明形式: 数据类型 ( * 指针变量名)常量表达式 例如:int ( * pb ) 6; 含义:定义了一个指向数组的指针pb,被指向的数组是一维的有6个元素的整型数组。,7-5 指针数组,共 20页 第 48 页,例C5_7101.C:将C5_3002.C中的week_day表用指针数组实现。 char * week_day8= “sunday“,“monday“, “tuesday“,“wednesday“,“thursday“, “friday“,“saturday“,NULL;,7-5 指针数组-输入字符串进行查找,NULL,共 20页 第 49 页,main函数的参数 main函数参数的一般形式: main ( argc, argv ) int argc; /* argc表示命令行参数个数 */ char *argv ; /* argv指向命令行参数的指针数组 */ 在操作系统下运行C程序时,可以使用命令行参数形式,向main函数传递参数。命令行参数的一般形式: 运行文件名 参数1 参数2 参数n,argv0,argv1,argv2,.,argvargc-1,文件名,第1个参数,第2个参数,第argc-1(n)个参数,数组argv,5-7 指针数组-main函数参数,argc=n+1,共 20页 第 50 页,例C5_7201.C:按数组方式引用命令行的参数。 #include main (argc, argv) int argc; char * argv ; int i; printf (“argc=%dn“, argc); for ( i=0; iargc; i+ ) printf(”%sn”, argvi); /* 按数组方式引用参数 */ ,5-7 指针数组-main函数参数实例,例C5_7201,例C5_7202.C:按指针方式引用命令行的参数。 #include main (argc, argv) int argc; char * argv ; int i; for (i=0; iargc; i+) printf(”%sn”, * argv + ); /* 按指针方式引用参数 */ ,例C5_7202,共 20页 第 51 页,有关指针的数据类型和指针运算小结,int * p; int * q4; int (* w)4; int * g( ); int (* y)( );,p 是一个指向整型数据的指针变量 根据优先级,q先和结合,所以 q 是一个指针数组,该数组有4个元素。 ( )内的*w指示出w是一个指针,指向一个含4个元素的一维数组。w是数组指针。 根据优先级,g先和( )结合,所以 g 是一个函数,*说明函数的返回值是指向整型数据的指针。 (*y)说明y是一个指针,( )表明此指针是指向函数的,函数的返回值是整型。,共 20页 第 52 页,指向多维数组的指针变量小结,多维数组名的性质 多维数组名是数组的首地址。例如:int a34; a是数组的首地址。,那么,a0、a1、a2 呢? 也是地址量。 把二维数组名,理解成下面的图。,共 20页 第 53 页,?,指向多维数组的指针变量小结,a 、 a0 是 a00的地址,是第一行的首地址。,a+1,、a1是 a10的地址,是第二行的首地址。,* a,是a0的内容,* * a 是 a00。,a 是二维数组,经过两次操作,才能访问到数组元素。 所以根据C的地址计算方法,a经过两次 * 操作才能访问到数组元素。这样有: * a是 a0的内容,* * a 才是 a00。 a0是a00的地址,*a0是a00的内容。,共 20页 第 54 页,指向多维数组的指针变量小结,例C5_901 已知 int a34=1,2,3,4,5,6,7,8,9,10,11,12; 求: A) *(a+6) B) *(&a0+6) C) *(a1+=2) D) *(&a00+6),例C9_303,指到数组元素之后第6个 指到数组元素之后第6个 a1是地址常量不能赋值 指向a12,例C5_901,共 20页 第 55 页,申请内存函数 (malloc) void * malloc ( unsigned size ) 功能:申请长度为size字节的内存区。若申请成功,函数返回所分配的内存区首字节的地址,即指向该内存的指针;若申请失败,函数返回NULL。 说明:函数malloc的返回值为指向void类型的指针。这是通用指针类型,在实际申请内存空间时,要按照实际指针所指对象的类型进行指针类型强制转换。 实例:要申请1个长度为10的整型数组空间,用指针指向数组的首地址,则可使用下列语句动态申请内存空间。 int * p; p = (int *) malloc( 10 * sizeof(int ) );,5-8 动态存储分配函数-malloc,共 20页 第 56 页,释放内存 (free) void free ( void * p ) 功能:释放p所指的内存空间。函数无返回值。这里p所指的内存区域必须是用函数malloc申请的内存空间,否则调用时使用其它指针,可能会破坏系统。 例C5_8001.C:动态申请10个元素的数组。 #include main ( ) int *p; p = (int *) malloc( 10 * sizeof(int) ); printf(“nResult:”); try ( p, 10); free(p); try ( int a , int m ) /* 以数组方式使用主函数空间 */ int k; for ( k=0; km; k+ ) a k = k*10; for ( k=0; km; k+ ) printf (“%d,”, ak); ,5-8 动态存储分配函数-free,例C5_8001,共 20页 第 57 页,例C5_5003.C:编写字符串复制函数。 main( ) char a30, b30; printf(“Enter string:“); scanf (“%s“, a); strcopy ( a, b ); /* 调用函数的实参为数组名 */ printf (“a=%snb=%sn“, a, b ); strcopy ( str1, str2 ) /* 将串str1拷贝到串str2中 */ char * str1, * str2; /* 形参为指向字符的指针 */ while ( (*str2 = *str1)!=0) /* 通过指针操作数组 */ str1+; str2+; ,5-5 数组与指针-串复制,例C5_5003,共 20页 第 58 页,例C5_50031.C:改进字符串复制函数。 改进一: strcopy ( str1, str2 ) char *str1, *str2; while ( *str2 = *str1 ) str1+; str2+; 改进二: strcopy ( str1, str2 ) char *str1, *str2; while ( *str2+ = *str1+ ) ; /* 通过指针操作数组 */ ,5-5 数组与指针-串复制,例C5_50031,例C5_50032,共 20页 第 59 页,例C5_5004.C:使用指针作为形式参数实现函数day_of_year。 #include main( ) static int day_tab213 = 0,31,28,31,30,31,30,31,31,30,31,30,31, 0,31,29,31,30,31,30,31,31,30,31,30,31 ; int y, m, d; scanf(“%d%d%d“, ,5-5 数组与指针-用指针操作二维数组,例C5_5004,共 20页 第 60 页,运行程序,分析运行结果。 #include ”stdio.h” #define SIZE 4 main( ) int datesSIZE,*pti,index; float billsSIZE,*ptf; pti=dates; ptf=bills; for ( index=0; indexSIZE; index+ ) printf(”pointer+%d:%10p%10p”,index,pti+index,ptf+index); 放大因子 由于指针所指的对象不同,在进行加减运算时,C语言会根据所指对象计算出不同的放大因子。 对于char,放大因子为 1;对于int,放大因子为 2;对于long,放大因子为 4;对于double,放大因子为 8。,5-6 指针的基本运算-放大因子,例C5_5000,共 20页 第 61 页,例C5_6101.C:编写函数,实现两个字符串的连接。 char * strcat(str1, str2) char *str1, *str2; char *p=str1; while ( *p!=0 ) p+; while ( *p+ = *str2+ ) ; return (str1); main( ) char a50, b30; printf(“Enter string 1:“); gets(a); printf(“Enter string 2:“); gets(b); printf(“a+b=%sn“, strcat(a, b) ); ,5-6 指针的基本运算-串连接,例C5_6101,/* 返回指向str

温馨提示

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

评论

0/150

提交评论