C语言课程ppt课件 第7章 指针.ppt

上传人:牧羊曲112 文档编号:1480411 上传时间:2022-11-30 格式:PPT 页数:68 大小:613.50KB
返回 下载 相关 举报
C语言课程ppt课件 第7章 指针.ppt_第1页
第1页 / 共68页
C语言课程ppt课件 第7章 指针.ppt_第2页
第2页 / 共68页
C语言课程ppt课件 第7章 指针.ppt_第3页
第3页 / 共68页
C语言课程ppt课件 第7章 指针.ppt_第4页
第4页 / 共68页
C语言课程ppt课件 第7章 指针.ppt_第5页
第5页 / 共68页
点击查看更多>>
资源描述

《C语言课程ppt课件 第7章 指针.ppt》由会员分享,可在线阅读,更多相关《C语言课程ppt课件 第7章 指针.ppt(68页珍藏版)》请在三一办公上搜索。

1、第7章 指针,苏小红,C语言大学实用教程,内容提要,指针的概念;难点:对指针数据类型的理解 数组的下标法引用和指针法引用;难点:二维数组的地址和指针概念 利用字符指针存取字符串;难点:字符数组和字符指针的区别与联系 指针数组应用;难点:指向数组的指针与指针数组的区别 带参数的main函数;动态内存分配函数及其应用;难点:一维、二维动态数组的实现动态数据结构(在第8章介绍),为什么引入指针的概念,指针为函数提供修改变量值的手段 指针为C的动态内存分配系统提供支持 指针为动态数据结构(如例链表、队列、二叉树等)提供支持 指针可以改善某些子程序的效率,计算机内的存储部件,所有指令和数据都保存在内存内

2、速度快,但是掉电即失可以随机访问只要指名要访问的内存单元的地址,就可以立即访问到该单元地址是一个无符号整数,其字长一般与主机相同内存中的每个字节都有唯一的一个地址地址按字节编号,按类型分配空间,内存(Random Access Memory)地址(Address),寻址方式,如何读写内存中的数据?通过变量的地址访问变量所在的存储单元两种寻址方式直接(寻址)访问直接按变量地址来存取变量内容的访问方式间接(寻址)访问通过指针变量来间接存取它所指向的变量的访问方式,关于指针的原则,学习原则一定要学会其实通常的应用很简单与使用变量几乎无异使用原则永远要清楚每个指针指向了哪里永远要清楚指针指向的位置是什

3、么,指针(Pointer)的概念,指针也是一种数据类型指针变量 具有指针类型的变量,专门存放地址数据的变量 变量的指针 变量的地址,如何定义指针变量?,定义指针变量int *p;定义了一个指针变量p,简称指针pp是变量,int*是类型p里保存一个地址。此时这个地址是哪呢(p指向哪呢)?指针变量初始化p = *p就像普通的变量一样使用,其值是p指向的内存的内容(在上例和a等价,但寻址方式不同)p可以动态(任意)地指向不同内存,从而使*p代表不同的变量,int i,*p;p=,int *p;float *q;p=q;,int i;float *p;p=,int *p;p=100;,判断是真?是假?

4、,指针变量只存放地址!,一个指针变量不能指向与其类型不同的变量!,我是真的,你猜对了吗?,应在类型相同的指针变量之间赋值,&与*操作符,*用来取指针指向地址的内容int i, *p;p = ,指针的指向,指针指向非其定义时声明的数据类型,将引起warningvoid*类型的指针可以指向任意类型的变量指针在初始化时一般int *p=NULL;NULL表示空指针,即无效指针但它只是逻辑上无效,并不是真正地无效如果指针指向一个非你控制的内存空间,并对该空间进行访问,将可能造成危险,指针变量与其它类型变量的对比,共性在内存中占据一定大小的存储单元先定义,后使用特殊性 它的内容只能是地址,而不能是数据必

5、须初始化后才能使用,否则指向不确定的存储单元只能指向同一基类型的变量可参与的运算:加、减一个整数,自增、自减、关系、赋值,指针运算(1/4),算术运算int *p, a10; p = a; p+; /*p的值增加多少?*/指针的加减运算是以其指向的类型的字长为单位的,6000600160026003600460056006,指针运算(2/4),int *p, *q, a10;p = a;q = 指针运算不能乱算一般只进行指针和整数的加减运算,同类型指针之间的减法运算其它运算,比如乘法、除法、浮点运算、指针之间的加法等,并无意义,所以也不支持,指针运算(3/4),关系运算只有指向同一种数据类型的

6、两个指针才能进行关系运算。值为1或0p q p q p = q指针不与非指针量进行比较,但可与NULL(即0值)进行等或不等的关系运算判断p是否为空指针P = NULLp != NULL,指针运算(4/4),赋值运算指针在使用前一定要赋值为指针变量赋的值必须是一个地址,main() int *p; scanf(%d,p); ,main() int a,*p= ,错!,指针与函数,指针既然是数据类型,自然可以做函数的参数和返回值的类型指针做参数的经典例子:两数的互换,void Swap(int *x,int *y) int temp; temp = *x; *x = *y; *y = temp;

7、,main() int a, b; a = 15; b = 8; Swap( ,void Swap(int x,int y) int temp; temp = x; x = y; y = temp;,main() int a, b; a = 15; b = 8; Swap(a, b); printf(a=%d,b=%d,a,b);,程序 1,程序 2,例7.2 :编写函数实现两数的互换,实 参,形 参,结果有何不同?,Not Work!Why?,主调函数,被调函数,main() int a, b; a = 15; b = 8; Swap(a, b); printf(a=%d,b=%d,a,b)

8、;,void Swap(int x, int y) int temp; temp = x; x = y; y = temp;,15,15,a,b,实 参,形 参,8,8,程序 1,x,y,简单变量作函数参数,图7-3 Swap函数调用前后参数变化的示意图,主调函数,被调函数,main() int a, b; a = 15; b = 8; Swap(,void Swap(int *x, int *y) int temp; temp = *x; *x = *y; *y = temp;,&a,&a,实 参,形 参,&b,&b,程序 2,x,y,15,a,b,8,指针变量作函数参数,swap函数的几种

9、错误形式(1/3),参数单向传递void Swap(int x, int y) int temp; temp = x; /*x,y为内部变量*/ x = y; y = temp;,swap函数的几种错误形式(2/3),参数单向传递void Swap(int *p1, int *p2) int *p; p = p1; /*p1,p2为内部变量*/ p1 = p2; p2 = p;,swap函数的几种错误形式(3/3),指针p没有确切地址void Swap(int *p1, int *p2) int *p; /*指针p未初始化*/ *p = *p1; *p1 = *p2; *p2 = *p;,例7

10、.3:打印出最高分及其学号,void FindMax(float score, long num, int n, float *pMaxScore, long *pMaxNum) int i;*pMaxScore = score0; *pMaxNum = num0; for (i=1; i *pMaxScore) *pMaxScore = scorei; *pMaxNum = numi; ,例7.4 :日期转换问题,任意给定某年某月某日,打印出它是这一年的第几天 已知某一年的第几天,计算它是该年的第几月第几日 static int dayTab213 = 0,31,28,31,30,31,30

11、,31,31,30,31,30,31, 0,31,29,31,30,31,30,31,31,30,31,30,31;,计算某年某月某日是这一年的第几天,/*函数功能:对给定的某年某月某日,计算出它是这一年的第几天 函数参数:整型变量year、month、day,分别代表年、月、日 函数返回值:这一年的第几天*/int DayofYear(int year, int month, int day) int i, leap; /*若year为闰年,则leap值为1,就用第2行元素dayTab1i计算, 否则leap值为0,用第1行dayTab0i计算*/leap = (year % 4 = 0)

12、/*返回计算出的day的值*/,计算某年的第几天是该年的第几月第几日,/* 函数功能: 对给定的某一年的第几天,计算它是这一年的第几月第几日 函数入口参数:整型变量year,存储年 整型变量yearDay,存储这一年的第几天 函数出口参数:整型指针pMonth,指向存储这一年第几月的整型变量 整型指针pDay,指向存储第几日的整型变量 函数返回值: 无*/void MonthDay(int year, int yearDay, int *pMonth, int *pDay) int i, leap;leap = (year % 4 = 0) /*将计算出的日号赋值给pDay所指向的变量*/,字

13、符串(String)与字符数组、字符指针,字符串一串以0结尾的字符在C语言中被看作字符串用双引号括起的一串字符是字符串常量,C语言自动为其添加0终结符C语言并没有为字符串提供任何专门的表示法,完全使用字符数组和字符指针来处理字符数组每个元素都是字符类型的数组char string100;字符指针指向字符类型的指针char* p;数组和指针可以等同看待,上面三者本质上是一回事,字符指针变量与字符数组的区别,定义方法不同 char str10; char *ptr;赋值方法和含义不同 char str10; ptr = ”china”; /*错误*/ strcpy(str,”china”); /*

14、正确*/ char *ptr; ptr = ”china”;,字符指针变量与字符数组的区别,在定义一个数组时,在编译时即分配单元,有确定地址,而定义一个字符指针变量时,如未对它赋初值,则其所指数据是不定的,因而使用是危险的。例如,输入字符串时 char str10; scanf(%s, str); /*正确*/ char *a; scanf(%s, a); /*错误*/ 应为: char *a; char str10; a = str; scanf(%s, a); /*正确*/,字符指针变量与字符数组的区别,初始化含义不同 char *pstr = ”china”; 等价于 char *pst

15、r; pstr = ”china”; char str14 = ”china”;不等价于 char str14; str = ”china”;字符指针是变量,而数组名是地址常量,例7.5 :字符串拷贝,方法1:用字符数组编程实现 /*函数功能: 字符串拷贝 函数参数: 字符型数组srcStr,存储源字符串 字符型数组dstStr,存储目的字符串 函数返回值:无*/void MyStrcpy(char dstStr, char srcStr)int i = 0; while (srcStri != 0) dstStri = srcStri; i+; dstStri = 0;,例7.5 :字符串拷

16、贝,例7.5 :字符串拷贝,方法2:用字符指针编程实现 /*函数功能: 字符串拷贝 函数参数: 字符型指针srcStr,指向源字符串 字符型指针dstStr,指向目的字符串 函数返回值:无*/void MyStrcpy(char *dstStr, const char *srcStr)while (*srcStr != 0) *dstStr = *srcStr; srcStr+; dstStr+; *dstStr = 0; ,例7.6 :计算实际字符个数,方法1:用字符数组实现/*函数功能: 计算字符串的长度函数参数: 字符型数组str,存储字符串函数返回值:字符串的长度*/unsigned

17、int MyStrlen(char str) int i;unsigned int len = 0; for (i=0; stri!=0; i+) len+; return (len);,例7.6 :计算实际字符个数,方法2:用字符指针实现/*函数功能: 计算字符串的长度函数参数: 字符型指针变量pStr,指向字符串函数返回值:字符串的长度*/unsigned int MyStrlen(char *pStr) unsigned int len = 0; for (; *pStr!=0; pStr+) len+; return (len); ,指针、数组以及其它的类型混合,基本数据类型int、l

18、ong、char、short、float、double指针是一种数据类型是从其它类型派生的类型XX类型的指针数组也是一种数据类型是从其它类型派生的类型每个元素都有一个类型任何类型都可以做指针或者数组的基础类型它们自己也可以做彼此或自己的基础类型,指针与一维数组,数组名就是一个指针只是不能修改这个指针的指向可以定义函数的参数为数组指针也可当作数组名使用int *p, a10;p = a;数组元素的几种等价引用形式ai*(a+i)pi*(p+i),60006001600260036004600560066007,a,a+1,a+2,60006001600260036004600560066007,

19、a,p+,p+,输入输出数组的全部元素,main() int a10; int i; for (i=0; i10; i+) scanf(%d, ,方法1:下标法,main() int a10; int *p, i; for (p=a; p(a+10); p+) scanf(%d, p); for (p=a; p(a+10); p+) printf(%d , *p);,方法2:指针法,例7.7 :插入排序,关键是:找到该插入的位置,然后依次移动插入位置及其后的所有元素腾出这一位置放入待插入的元素,例7.7 :插入排序,void Inseart(int a, int n, int x) int i

20、, pos; for (i=0; (i ai); i+) pos = i; for (i = n-1; i = pos; i-) ai+1 = ai; /*向后移动*/apos = x; /*插入元素x到位置pos*/,指针与二维数组,指针与二维数组,C语言将二维数组看作一维数组,其每个数组元素又是一个一维数组,aa0+0,a+1a1+0,a0+1,a0+2,&a00,&a10,&a11,a1+1,&a12,&a01,&a02,a1+2,int a23;,指针与二维数组,例7.8,任意输入英文的星期几,在查找星期表后输出其对应的数字。 char weekDay710 = Sunday, Mon

21、day, Tuesday,Wednesday, Thursday, Friday, Saturday;,表7-1 星期表的内容,例7.8,#include main() int i, pos;int findFlag = 0; char x10;char weekDay10 = Sunday,Monday,Tuesday, Wednesday,Thursday,Friday, Saturday; printf(Please enter a string:);scanf(%s, x); for (i=0; i7 ,指针与二维数组,a 代表二维数组的首地址,第0行的地址a+i 代表第i行的地址*(

22、a+i) 即 ai 代表第i行第0列的地址*(a+i)+j 即 ai+j 代表第i行第j列的地址*(*(a+i)+j ) 即 aij 代表第i行第j列的元素,行地址转变成列地址,指针与二维数组,元素aij的地址的几种等价的引用方式&aij ai+j *(a+i)+j &(*(a+i)j元素aij的几种等价的引用方式aij *(ai+j) *(*(a+i)+j) (*(a+i)j,指针与二维数组,二维数组的指针列指针int *p;p = *a;/用列地址初始化相对于数组起始地址的偏移量i*m+jfor (i=0; in; i+)for (j=0; jm; j+) printf(%d,*(p+i*

23、m+j);,p,p+,指针与二维数组,二维数组的指针行指针int (*p)3;p = a;/用行地址初始化for (i=0; in; i+)for (j=0; jm; j+) printf(%d,*(*(p+i)+j);,p,p+,例7.9 :求最高分及其所在班级和学号,int FindMax(int *p, int m, int n, int *pRow, int *pCol) int i, j, max;max = p0; *pRow = 0; *pCol = 0; for (i=0; i max) max = pi*n+j; *pRow = i; *pCol = j; return (m

24、ax);,指针数组,元素均为指针类型数据的数组,称为指针数组 定义形式为: 类型关键字 *数组名数组长度;例如 char *pStr5;,例7.10:字符串按字典顺序排序,char strN10 = Pascal,Basic,Fortran, Java,Visual C; for (i=0; iN-1; i+) for (j = i+1; jN; j+)if (strcmp(strj, stri) 0) strcpy(temp,stri); strcpy(stri,strj); strcpy(strj,temp); ,方法1:二维数组,方法1排序前后,例7.10:字符串按字典顺序排序,char

25、 *ptrN = Pascal,Basic,Fortran, Java,Visual C;for (i=0; iN-1; i+) for (j = i+1; jN; j+) if (strcmp(ptrj, ptri) 0) temp = ptri; ptri = ptrj; ptrj = temp; ,方法2:指针数组,方法2排序前后,指向指针的指针,如果指针变量中保存的是另一个指针变量的地址,这样的指针变量就称为指向指针的指针多级指针实质就是多级间接寻址(Multiple Indirection)定义形式: 类型关键字 *变量名;,例,main() int i = 5; int *ip =

26、 ,例7.11,main() int i; char *ptr = Pascal,Basic,Fortran, Java,Visual C; char *p; p = ptr; for (i=0; i5; i+) printf(%sn, *p); p+; ,命令行参数,通过命令行参数,使用户可以根据需要来决定我们的程序干什么、怎么干main(int argc, char* argv)当你把main函数写成这样时argc的值为程序执行时参数的数目(包括命令本身)argvX为指向每个参数的字符指针这两个内设形参用于接收命令行参数,例7.12:演示命令行参数与main函数各形参之间的关系,main(

27、int argc, char *argv)int i;printf(The program name is:%sn, argv0);if (argc 1)printf(The other arguments are following:n);for (i = 1; iargc; i+) printf(%sn, argvi);,动态分配内存,在 和中均定义了下面的函数void* malloc(unsigned int size);向系统申请大小为size的内存块,把首地址返回。如果申请不成功,返回NULLvoid *calloc(unsigned int num, unsigned int si

28、ze);向系统申请num个size大小的内存块,把首地址返回。如果申请不成功,返回NULLvoid free(void* p);释放由malloc()和calloc()申请的内存块。p是指向此块的指针,例7.13:一维动态数组,#include main()int *p = NULL, n, i, sum;printf(Please enter array size:);scanf(%d, ,例7.14:二维动态数组,#include main()int *pScore = NULL, i, j, m, n, maxScore, row, col; printf(Please enter array size m,n:);scanf(%d,%d, ,这一章我们学习了,指针的概念指针是一种特殊的数据类型永远要清楚每个指针指向了什么位置 永远要清楚每个指针指向的位置中的内容是什么 指针与数组之间的关系掌握二维数组在内存中的存放方式,是理解二维数组的行指针和列指针的关键指针的应用做函数参数,传地址调用动态分配内存,实现动态数组,对于动态分配的内存,不要忘记在不使用时释放,作业,P286289,7.1(5),7.27.4P289,7.77.8,

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号