C语言详解指针和数组.ppt

上传人:tia****nde 文档编号:11495480 上传时间:2020-04-25 格式:PPT 页数:65 大小:300KB
返回 下载 相关 举报
C语言详解指针和数组.ppt_第1页
第1页 / 共65页
C语言详解指针和数组.ppt_第2页
第2页 / 共65页
C语言详解指针和数组.ppt_第3页
第3页 / 共65页
点击查看更多>>
资源描述
再论指针和数组,附录一,预习检查,链表单元有哪几个部分组成如何申请链表单元,及释放链表单元实现单链表插入的基本语法简述一下快速排序基本理论要点,课程目标,本章概述指针与数组什么时候相同C语言为什么把数组参数当作指针C语言的多维数组,及如何创建动态数组。本章目标掌握指针什么时候和数组相同,以为容易混淆的原因掌握多维数组的内存布局。使用指针向函数传递多维数组参数使用指针返回多维数组使用指针创建和使用动态数组重点指针和数组混淆的原因指针传递多维数组参数难点指针和数组混淆的原因创建和使用动态数组,本章结构,指针与数组不相同,再论指针和数组,指针数组和数组指针,指针与数组相同,函数指针和指针函数,怎样使用数组,指针运算,1再论指针和数组,指针与数组的不相同指针与数组的相同怎样使用指针指针运算函数指针和指针函数指针数组和数组指针,1.1指针与数组的不相同,数组和指针是如何访问的数组访问指针数据使声明与定义相匹配数组和指针的其他区别,1.1.1数组和指针是如何访问的,申明区别externint*x;声明x是个int型的指针externintyy是个int型数组,长度尚未确定地址和内容的区别,1.1.1数组和指针是如何访问的,数组下标引用特点地址在编译时可知直接进行操作例:数组:chara9“abedefgh”;.取值:c=ai,编译器符号表具有一个地址9980,运行步骤:取i的值,将它与9980相加取地址(9980i)的内容。,图A,1.1.2数组访问指针数据,指针访问特点必须首先在运行时取得它的当前值间接进行操作例:指针:char*p取值:c=*p,编译器符号表有一个符号p,它的地址为4624,运行步骤:取地址4624的内容,就是5081取地址5081的内容。,5081,4642,图B,1.1.2数组访问指针数据,数组访问指针特点对内存进行直接的引用转化为间接引用例:数组:chara9“abedefgh”;.取值:c=ai,编译器符号表有一个符号p,它的地址为4624,运行步骤:1.取地址4624的内容,即5081。2.取得i的值,并将它与5081相加。3.取地址508l+i的内容。,5081,4642,5081+i,图C,1.1.2数组访问指针数据,指针访问特点char*p=“abcdefgh”;p3dchara=”abcdefgh”;a3d访问特点取得符号表中P的地址,提取存储于此处的指针。把下标所表示的偏移量与指针的值相加,产生一个地址。访问上面这个地址,取得字符。,1.1.3数组和指针的其他区别,1.2指针与数组的相同,什么时候指针与数组相同混淆的原因数组和指针规则为什么C语言把数组形参当作指针数组与指针归纳总结,1.2.1什么时候指针与数组相同,数组运用特性数组声明外部数组(externalarray)的声明数组的定义函数参数的声明运用特性作为函数参数的数组名可以通过编译器转换为指针使用数组时,数组可以写成指针,可以互换,1.2.1什么时候指针与数组相同,数组与指针编译器处理时是不同的一个数组就是一个地址一个指针就是一个地址的地址在运行时的表示形式也是不一样的可能产生不同的代码,1.2.2数组和指针混淆的原因,分析:,charmy_array10char*my_ptr;.j=strlen(my_array);J=strlen(my_ptr);printf(”ss”,my_ptr,my_array);,1.2.2数组和指针混淆的原因,数组和指针是相同的规则表达式中的数组名(与声明不同)被编译器当作一个指向该数组第一个元素的指针1。下标总是与指针的偏移量相同在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针,1.2.3数组和指针规则,“表达式中的数组名”就是指针C语言把数组下标作为指针的偏移量“作为函数参数的数组名”等同于指针,1.2.3.1“表达式中的数组名”就是指针,数组下标的引用一个指向数组的起始地址的指针加上偏移量”下标值的步长调整到数组元素的大小整型数的长度是4个字节,那么ai+1和ai在内存中的距离就是4(而不是1)例:访问ai:inta10;int*p;Inti=2;,p=a;pi;,p=a;*(p+i);,p=a+i;*p;,访问数组第i个元素的三张方式,1.2.3.1“表达式中的数组名”就是指针,数组的引用不能用指向该数组第一个元素的指针规则数组作为sizeof()的操作数一显然此时需要的是整个数组的大小,而不是指针所指向的第一个元素的大小。使用c=piFunc(char*p);c=pi编译器符号表显示p可以取址,从堆栈指针sp偏移14个位置运行时步骤1:从sp偏移14个位置找到函数的活动记录,取出实参。步骤2:取i的值,并与5081相加。步骤3:取出地址(508i)的内容。,1.2.4为什么C语言把数组形参当作指针,数组,指针实参的一般用法,1.2.5数组与指针归纳总结,用ai这样的形式对数组进行访问总是被编译器“改写”或解释为像*(a+1)这样的指针访问。指针始终就是指针。它绝不可以改写成数组。在特定的上下文中,也就是它作为函数的参数(也只有这种情况),一个数组的声明可以看作是一个指针。作为函数参数的数组(就是在一个函数调用中)始终会被编译器修改成为指向数组第一个元素的指针。当把一个数组定义为函数的参数时,可以选择把它定义为数组,也可以定义指针。不管选择哪种方法,在函数内部事实上获得的都是一个指针。定义和声明必须匹配,1.3怎样使用数组,多维数组向函数传递一个多维数组从函数返回一个数组,1.3.1多维数组,多维数组特性多维数组内存布局如何分解多维数组如何对数组进行初始化,1.3.1.1多维数组特性,定义和引用多维数组惟一的方法就是使用数组的数组注意:ijk与I,j,k多维数组看作是一种向量多维数组的定义声明一个1020的多维字符数组charcarrot1020;或者声明一种看上去更像“数组的数组”形式:typedefcharvegetable20;vegetablecarrot10;不论哪种情况,访问单个字符都是通过carrotij的形式,编译器在编译时会把它解析为*(*(carrot+i)+j)的形式,1.3.1.2多维数组的内存布局,多维数组内存布局pea12的内存表示:线性存储表达式为:*(*(pea+i)+j),Pea0,Pea1,Pea1,Pea1,Pea0123,Pea12,1.3.1.3如何分解多维数组,分解特点:多维数组是如何分解为几个单独的数组的多维数组每一个单独的数组都可以看作是一个指针不能把一个数组赋值给另一个数组多维数组分解intapricot235sizeof(apricot)区域sizeof(apricoti)sizeof(apricotij)sizeof(apricotijk),1.3.1.4如何对数组进行初始化,嵌套的花括号进行初始化多维数组如shortcantaloupe25=10,12,3,4,一5,31,22,6,0,-5,;如intrhubarb3=0,0,0,1,1,1,;,1.3.1.4如何对数组进行初始化,建立指针数组进行初始化多维数组如如,只有字符串常量才可以初始化指针数组指针数组不能由非字符串的类型直接初始化int*weights=1,2,3,4,5,6,7,8,9,10;,charvegetables9=“carrot”,“celery”,“corn”,“cilantro”,“crispyfriedpatatoes”,char*vegetables=“carrot”,“celery”,“corn”,“cilantro”,“crispyfriedpatatoes”,1.3.1.4如何对数组进行初始化,建立数组进行初始化多维数组如:,introw_1=1,2,3,4,5,-1;*一1是行结束标志*introw_2=6,7,-1;introw_3=8,9,10,-1;int*weight=row_1,row_2,row_3;,1.3.2向函数传递一个多维数组,方法1模式:my_function(intmy_array1020);特点:最简单的方法作用最小的例子,inta33=1,1,1,2,2,2,3,3,3;/函数定义voidFunc(intarray33);,Main()/函数调用Func(a33);,1.3.2向函数传递一个多维数组,方法2模式:my_function(intmy_array20);例:方法3(指针传递模式)模式:my_function(char*my_array),inta33=1,1,1,2,2,2,3,3,3;/函数定义voidFunc(int*array);,Main()/函数调用Func(a);,1.3.3从函数返回一个数组,怎样返回一个数组一个指向任何数据结构的指针一个指向数组的指针例:,int(*pal()20;int(*pal()20/*声明一个指向包含20个int元素的数组的指针*/int(*pear)20;pear=calloc(20,sizeof(int);if(!pear)longjmp(error,1);returnpear;,阶段小节,数组在什么时候和指针相同数组与指针混淆原因是什么数组当作函数传递的好处是什么如何向一个函数传递一维数组,1.4指针运算,什么是间接引用最多可以使用几层指针void指针与空指针指针运算,1.4.1什么是间接引用,间接引用:指向变量或内存中的对象的指针指针就是对对象值的间接引用一个间接引用的例子,#includeIntmain()inti;int*p;i=5;p=/*seeFAQXVI.4*/,1.4.2最多可以使用几层指针,一个指针时最多可以包含几层间接引用至少可以有12层如:最多可以使用多少层指针而不会使程序变得难读不要使用两层以上的指针程序运行时最多可以有几层指针无限层,inti=0;int*ip0l=,1.4.2最多可以使用几层指针,例:一个有无限层间接引用的循环链表,/*WouldrunforeverifyoudidntlimitittoMAX*/#includestructcirc_listcharvalue3;structcirc_list*next;structcirc_listsuffixes=th,#defineMAX20main()inti=0;structcirc_list*p=suffixes;while(ivalue);+i;p=p-next;,1.4.3void指针与空指针,什么是空指针什么是void指针NULL总是被定义为0吗,1.4.3.1什么是空指针,空指针并不指向任何对象指针值是NULL,NULL可能是0,0L或(void*)0绝对不能间接引用一个空指针,1.4.3.1什么是空指针,空指针的用法用空指针终止对递归数据结构的间接引用用空指针作函数调用失败时的返回值用空指针作警戒值,1.4.3.2什么是void指针,void指针通用指针或泛指针不属于任何类型常常用作函数指针内存操作内存操作例子char*strepy(charstrl,constchar*str2);char*strncpy(char*strl,constchar*str2,size_tn);void*memcpy(void*addrl,void*addr2,size_tn);,1.4.3.3NULL总是被定义为0吗,NULL与NULL不是被定义为0,就是被定义为(void*)0,if(/*/)pNULL;elsep/*somethingelse*/;/*/if(p0),1.4.4指针运算,两个指针可以相减吗把一个值加到一个指针上意味着什么两个指针可以相加吗,1.4.4.1两个指针可以相减吗,如果两个指针向同一个数组,它们就可以相减,其为结果为两个指针之间的元素数目如果两个指针不是指向一个数组,它们相减就没有意义指针相减的结果是某种整类型的值ptrdiff_t,1.4.4.1两个指针可以相减吗,指针的相减运算,#include#includestructstuffcharnamel6;structstuffarray=The,quick,brown,fox,jumped,over,the,lazy,dog.,;,main()structstuff*p0=/*seeFAQXVI.4*/,1.4.4.2把一个值加到一个指针上意味着什么,当把一个整型值加到一个指针上后,该指针指向的位置就向前移动了一段距离这段距离对应的字节数等于该值和该指针所指向的对象的大小的乘积,1.4.4.3两个指针可以相加吗,两个指针是不能相加的如:p=(p+p2)-p1;正确的语句应该是:pp+(p2-p1);对此例来说,使用下述语句更好:p+p2-p1;,1.5函数指针和指针函数,指针函数函数指针函数指针的用法,1.5.1指针函数,定义:指带指针的函数,即本质是一个函数语法:返回类型标识符*返回名称(形式参数表)函数体特点:返回类型可以是任何基本类型和复合类型返回一个指针变量的值可以把整个函数看成一个变量,1.5.1指针函数,例子:,函数定义:,#include“stdio.h”float*find();main()staticfloatscore4=60,70,80,90,56,89,34,45,34,23,56,45;float*p;inti,m;printf(Enterthenumbertobefound:);scanf(%d,/*定义指针函数*/float*find(float(*pionter)4,intn)float*pt;pt=*(pionter+n);return(pt);,1.5.2函数指针,定义:指向函数的指针变量语法:数据类型标志符(*指针变量名)(参数)特点:是指针变量指向类型为函数可用该指针变量调用函数,1.5.2函数指针,例子:,函数定义:,voidmain()int(*ptr)();inta,b,c;ptr=max;scanf(%d,%d,/*定义函数*/intmax(intx,inty)return(xy?x:y);,1.6函数指针的用法,定义函数指针类型/定义一个原型为intFun(inta);的函数指针typedefint(*PTRFUN)(intaPara);,函数指针变量的定义PTRFUNpFun;/pFun为函数指针变量名int(*pFun2)(inta);/pFun2也是函数指针变量名,1.6函数指针的用法,函数指针作为函数的参数传递定义回调函数定义回调者函数使用回调,intCallBack(inta)return+a;,voidCaller(PTRFUNcb)/voidCaller(int(*cb)(int)/也可这样申明intnPara=1;intnRet=cb(nPara);,voidTest()Caller(CallBack);/直接使用回调函数PTRFUNcb=CallBack;/int(*cb)(int);cb=CallBack;intnRet1=cb(99);/nRet1=100;,阶段小节,指针在什么时候可以实现相加减空指针与void指针指针函数的申明和赋值函数指针的传递和调用指针数组的定义和初始化,本章总结,指针与数组不相同,再论指针和数组,指针数组和数组指针,指针与数组相同,函数指针和指针函数,怎样使用数组,指针运算,本节主要讲述了指针和数组的互访及其区别,讲述了指针和数组的相同点,以及分析他们之间的混淆原因,简单讲述了多维数组,并深入讲述数组和函数的应用,深入具体的讲述指针的运算,了解指针函数和函数指针的区别,并深入讲述函数指针的用法,了解指针数组和数组指针的区别,实验项目,题目写一个排序函数,要求实用两种参数传递模式。并采用函数指针调用模式实现的排序函数,并输入排序的最终结果实验目的回顾上章节的排序算法应用;数组的参数传递和数组及指针互用操作;函数指针的实现和调用;实验分析定义排序函数,采用传指针和传数组两种方式;用typedef定义函数指针;调用函数指针;输出最终的排序结果;,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


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

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


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