




已阅读5页,还剩61页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第8章内存的高效管理,变量的内存地址指针指针与函数指针与数组动态存储分配,【本章要点】,8.1引例,8.1.1问题描述电子商务活动中的贸易双方达成网上支付协议后,为了防止被非法窃取信息,需要设计文字加密软件。模拟这一问题,设计一个简单的文字加密程序,对键盘上输入的一个句子加密后输出。加密规则是:将一个句子中每个单词的第一个字母移到该单词的末尾再加上ay。如:jumpumpjay。,8.1.2问题分析依据加密规则,文字加密操作应以单词为单位进行,鉴于对每个单词的操作相同,可以设计一个单词加密函数,通过反复调用该函数实现对一个句子的加密。在C语言中,采用字符串描述文字信息,通过其首地址加以访问。因此,文字加密函数应该以字符串首地址为参数,通过采用逐个扫描字符串中每个字符的方式实现加密并输出结果。,8.1引例,8.1.3算法设计1.定义文字加密函数,实现对单词的加密,函数形参为单词首地址;函数体中,从单词的第二个字母开始逐个输出单词中每一个字母,最后输出首字母和字符串ay;函数值类型为void。2.主函数从给定的句子中拆分出各个单词,对每个单词调用以上文加密函数输出加密后的内容。,8.1引例,8.2指针,8.2.1变量的内存地址程序中定义一个变量的实质就是从内存中获取相应的存储单元,并采用变量名标识该存储单元。而且在程序编译链接时,系统会给每个变量的存储单元分配一个地址(即内存地址),该地址可以通过取地址运算符“printf(a的地址是:%pnb的地址是:%pnc的地址是:%pn,8.2指针,例8-1分析下面程序的运行结果。#includevoidmain()inta,b,c;printf(a的地址是:%pnb的地址是:%pnc的地址是:%pn,8.2指针,程序的运行结果:,8.2指针,8.2.2指针与指针变量内存单元的地址称为指针,它指出了该单元在内存中的位置。保存内存地址的变量称为指针变量。1.定义指针变量定义指针变量的格式:基类型*指针变量名;其中,基类型表示该指针变量所指向变量的类型。,8.2指针,8.2.2指针与指针变量内存单元的地址称为指针,它指出了该单元在内存中的位置。保存内存地址的变量称为指针变量。1.定义指针变量定义指针变量的格式:基类型*指针变量名;其中,基类型表示该指针变量所指向变量的类型。,8.2指针,8.2.2指针与指针变量例如:int*ptr;定义指针变量ptr,用于存储整型变量的地址。又如:char*cPtr;定义指针变量cPtr,用于存放字符型变量的地址,也可以存放一个字符串常量的首地址。,8.2指针,8.2.2指针与指针变量2.指针变量的初始化在定义指针变量的同时赋予初始值的操作称为指针变量的初始化。例如:char*sPtr=hello!;/sPtr指向字符串hello!的首地址double*dPtr=NULL;/dPtr不指向任何对象,8.2指针,8.2.2指针与指针变量3.指针变量的赋值与引用将一个变量的地址赋给指针变量的格式为:指针变量=注意:(1)指针变量中只能存放地址。(2)赋值语句中的变量类型必须与指针变量的基类型相同。,8.2指针,8.2.2指针与指针变量3.指针变量的赋值与引用引用指针变量的方式有两种:(1)通过指针变量名获取所指变量的地址。(2)通过指针运算符“*”获取所指变量的值。格式:*指针变量名。,8.2指针,例8-2观察下面的简单程序,理解指针变量赋值与引用方法。#includevoidmain()intx=10;int*pt;pt=,8.2指针,8.2.3指针运算1.算术运算(1)指针+整数(运算结果是指针)设有指针p和整数n,则表达式p=p+n表示指针向前移动n个存储单元。,8.2指针,比如,若有定义:inti;int*p=则表达式p=p+2将p指针向前移动2个整型单元,即p的值增加8个字节。假设变量i的地址是0012FF10,指针变化情况如图所示。,8.2指针,例8-3初步实现引例中对给定单词加密的功能:将单词“good”的第一个字母移到该单词的末尾再加上ay。问题分析:将单词首地址赋给字符型指针变量word,用word+i表示第i+1个字母的地址。采用循环结构,设指针p为循环变量,循环体中令p依次指向单词中每个字母,并输出*p。循环体外输出*word和ay。p的初值为word+1,循环条件为*p!=0,每执行一次循环体,p指针加1。,8.2指针,算法设计:,程序设计:#includevoidmain()char*word,*p;word=good;printf(单词good加密后变为:n);for(p=word+1;*p!=0;p+)printf(%c,*p);printf(%c%sn,*word,ay);,8.2指针,运行结果:,8.2指针,8.2.3指针运算1.算术运算(2)指针-整数(运算结果是指针)p=p-n表示指针向后移动n个p所指类型的单元,若使指针p向后移动1个单元则可用p-表示。(3)指针-指针两个同类型的指针相减,得到的是两个指针所指单元之间相差的单元数。,8.2指针,8.2.3指针运算2.关系运算对于两个同类型的指针变量可以进行关系运算,用于比较两个地址的大小。常用于判断一个指针是否为NULL。,8.3指针与函数,8.3.1指针作函数参数指针型参数的格式:数据类型*形式参数,#includevoidswap(int*xPtr,int*yPtr)inttemp;temp=*xPtr;*xPtr=*yPtr;*yPtr=temp;voidmain()intx=10,y=20;swap(,例8-4设计swap()函数交换两个整型变量的值,主函数调用该函数进行数据交换。,8.3指针与函数,例8-5将例8-3改写为一个对任意单词加密的函数。问题分析:定义单词加密的函数,需要将表示单词的字符串首地址传入函数中,函数形参应为字符型指针;加密后的单词可以直接打印输出,因此函数值的类型可为void。,8.3指针与函数,定义加密函数:voidprintPigLatin(char*word)char*p;printf(单词good加密后变为:n);for(p=word+1;*p!=0;p+)printf(%c,*p);printf(%c%sn,*word,ay);定义主函数测试printPigLatin()函数的功能:voidmain()printPigLatin(good);,8.3指针与函数,8.3.2返回指针的函数返回指针的函数是指函数的返回值为内存地址。在定义该函数时,应将函数值类型声明为指针型。例8-6设计函数,返回字符串中第一次出现的a的地址,若a不存在则返回NULL。,8.3指针与函数,问题分析:首先需要将待处理字符串的首地址传入函数中,故形参应为字符型指针;函数值返回a的地址(或找不到a返回NULL)也应为字符型指针。算法设计:采用顺序查找的方法,从第一个字符开始,逐个查找a。可采用循环结构。,8.3指针与函数,程序设计:#includechar*find(char*str)while(*str!=0)if(*str=a)return(str);elsestr+;return(NULL);voidmain()char*s=happynewyear;char*cPtr=find(s);printf(字符%c第一次出现的地址是:%pn,*cPtr,cPtr);,8.3指针与函数,例8-7实现引例中拆分单词的功能,输出拆分后的单词。假定句子中的标点符号只有句号。问题分析:根据题意,句子中单词之间出现的字符只有句号和空格,应以这两种字符作为拆分字符分离出所有单词。C语言中的拆分单词函数strtok()可直接调用。函数原型:char*strtok(char*s,char*delim);功能:在参数s所指的字符串中搜索参数delim所包含的各拆分字符,若发现拆分字符则将该字符改为0,并返回被拆分出的子串地址;否则返回NULL。,8.3指针与函数,说明:(1)在使用strtok()函数时应该包含头文件string.h。(2)在第一次调用strtok()函数时必需给参数s传字符串,往后的调用则应将参数s设置成NULL。(3)strtok()函数会破坏原字符串的完整性,调用前和调用后的s已经不一样了。本例中调用strtok()函数时,需要将待拆分的句子传递给参数s;将空格、句号组成的拆分字符串“.”传递给参数delim。,8.3指针与函数,程序设计:#include#includevoidmain()charsentence81;char*tokenPtr;printf(请输入一个英文句子:n);gets(sentence);printf(拆分单词如下:n);tokenPtr=strtok(sentence,.);while(tokenPtr)printf(%sn,tokenPtr);tokenPtr=strtok(NULL,.);,8.4指针与数组,8.4.1指针与一维数组1.数组元素的两种表示方法(1)下标法(2)指针法。指针法是指通过指针的“*”运算符表示数组元素的值。比如,数组a中第i个元素ai的指针表示为:*(a+i)。,8.4指针与数组,8.4.1指针与一维数组1.数组元素的两种表示方法例8-8采用指针法对数组元素赋值并打印。问题分析:设数组名为a,则对于数组元素ai及其地址,采用指针法表示时分别为:*(a+i)和a+i。,8.4指针与数组,程序设计:#includevoidmain()inta5,i;printf(请输入五个数:n);for(i=0;i5;i+)scanf(%d,a+i);printf(数组中元素为:n);for(i=0;i5;i+)printf(%d,*(a+i);printf(n);,2.指向数组元素的指针定义指向数组元素的指针与定义指向普通变量的的指针方法相同。但在定义时的指针类型应和数组元素的类型一致。,8.4指针与数组,2.指向数组元素的指针例8-9用指向数组元素的指针对数组元素赋值并打印。问题分析:根据题意,可先令指针指向数组起始地址,在进行赋值或打印操作后指针下移(p+),处理下一个元素。算法设计:采用循环结构实现对每个元素的赋值或打印操作。,8.4指针与数组,程序设计:#includevoidmain()inta5,i;int*p;p=a;printf(请输入五个数:n);for(i=0;i5;i+)scanf(%d,p);p+;p=a;printf(数组中元素为:n);for(i=0;i5;i+)printf(%d,*p);p+;printf(n);,8.4指针与数组,2.指向数组元素的指针例8-9用指向数组元素的指针对数组元素赋值并打印。问题分析:根据题意,可先令指针指向数组起始地址,在进行赋值或打印操作后指针下移(p+),处理下一个元素。算法设计:采用循环结构实现对每个元素的赋值或打印操作。,8.4指针与数组,讨论:程序中可以不移动p指针,而是用五个表达式p+0、p+1、p+2、p+3、p+4分别表示a0、a1、a2、a3、a4的地址,进而通过*(p+0)*(p+4)表示a0a4的值。程序可改写为:#includevoidmain()inta5,i;int*p;p=a;printf(请输入五个数:n);for(i=0;i5;i+)scanf(%d,p+i);printf(数组中元素为:n);for(i=0;i5;i+)printf(%d,*(p+i);printf(n);,8.4指针与数组,8.4指针与数组,小结:数组a中元素的多种表示形式,8.4指针与数组,注意a和p有着本质的区别:a是指针常量,表示数组首地址,不能通过赋值的方式改变其值;p是指针变量,可以不断给p赋予新值。只有在执行了赋值操作p=a后,二者都表示数组的起始地址,其后对数组元素的表示才可以相互替代,但p+不能写成a+。,例8-10设有整型数组a10,对a中的元素进行逆序操作。问题分析:使数组中元素逆序,只需从数组的两端开始两两对调元素的值。算法设计:用指针p和q分别指向数组中首尾两个元素:p=inti,*p,*q,temp;printf(原始数组:n);for(i=0;i10;i+)printf(%d,ai);printf(n);p=,8.4指针与数组,8.4.2指针与二维数组,8.4指针与数组,矩阵,对应的二维数组,8.4.2指针与二维数组二维数组的各行均构成一个一维数组,数组名分别为a0、a1、a2。因此,二维数组a可以看成是由a0、a1、a2组成的数组。,8.4指针与数组,8.4.2指针与二维数组1.行指针变量在二维数组a中,a0、a1、a2作为数组名分别表示其所在行的首地址。因此,可以采用指针变量p指向a0,向下移动指针p即可指向a1和a2,称p为行指针变量,亦即指向数组的指针。,8.4指针与数组,8.4.2指针与二维数组一般地,定义指向一维数组的指针变量(行指针变量)的格式是:数据类型名(*指针变量名)n其中,n表示数组中元素的个数。例如:int(*p)4;定义了一个指向含有4个整型元素的一维数组的指针变量p。,8.4指针与数组,8.4.2指针与二维数组若有赋值语句:p=a;将数组行元素a0的地址赋给p(即p指向a0),则执行p+操作可使p指向a1;再执行p+操作,则p指向a2。,8.4指针与数组,8.4.2指针与二维数组2.列指针变量设有以下语句:int*q;q=a0;则q被定义为一个指向整型变量的指针,并指向a0数组的首地址(即a00的地址)。随着q+操作的执行,q依次指向a01、a02、a03等。称q为列指针变量。,8.4指针与数组,8.4.2指针与二维数组2.列指针变量,8.4指针与数组,8-11阅读程序,理解指针用法。#includevoidmain()inta23;int(*p)3;/*行指针*/int*q;/*列指针*/inti,j;printf(请输入二维数组a的6个元素:n);for(i=0;i2;i+)for(j=0;j3;j+)scanf(%d,8.4指针与数组,8.4.3指针数组定义指针数组的格式:元素类型*数组名元素个数;例如:char*str3;定义了一个字符型指针数组,可以存储3个字符型地址。,8.4指针与数组,8.4.3指针数组例8-12设计程序,将键盘输入的表示月份的12个数字转换成英文名称输出。问题分析:12个月的英文名称分别是一个字符串常量,其地址可分别存储在指针数组str中下标为011的单元内。根据月份和数组下标的对应关系可知,第i个月的名称存放在stri-1中。这样,对于键盘输入的i值,直接输出stri-1即可。,8.4指针与数组,程序设计:#includevoidmain()char*str=January,February,March,April,May,June,July,August,September,October,November,December;inti;printf(月份转换n);printf(请输入月份:);scanf(%d,8.4指针与数组,例8-13阅读下面程序,对比指针的各种用法。#includevoidmain()inti;chars=abcdef;/*s为字符数组*/char*t=abcdef;/*t为指向字符数组的指针变量*/*p为指针数组,p中元素依次指向字符串abcdef,qhijk,lmnop,qrstuv*/char*p=abcdef,ghijk,lmnop,qrstuv;/*测试p0、*(p+0)、*p三者是否相同*/printf(下述等式成立吗?p0=*(p+0)=*pnn);if(p0=*(p+0),8.4指针与数组,用于动态内存管理的函数有:malloc()、calloc()、realloc()、free()等。这些函数定义在头文件stdlib.h中,使用时应包含stdlib.h。,8.5动态存储分配,8.5.1malloc函数函数原型:void*malloc(unsignedsize)功能:从内存中分配size个字节的存储空间,若分配成功,返回存储空间的首地址;若没有足够的内存分配,则返回NULL。其中void*是一种“通用”指针类型,表示可将函数值赋给任何数据类型的指针变量,也可以将其强制类型转换后再赋给相应指针变量。,8.5动态存储分配,8.5.1malloc函数比如,分配一个长度为4字节的单元,将地址赋给整型指针p。应该如下表示:p=malloc(4);或者p=(int*)malloc(4);说明:(1)在动态申请存储空间时,若不能确定存储空间所占的字节数,可以通过sizeof运算符得到。(2)动态分配的存储空间没有名字,只能通过指针引用。,8.5动态存储分配,例8-14下面的程序动态分配一个double型存储单元并对其赋值。阅读并理解程序。#include#includevoidmain()double*p;p=(double*)malloc(sizeof(double);if(p=NULL)printf(没有足够的空间n);exit(1);*p=25;printf(动态分配的单元地址是:%pn,p);printf(其中的数据是:%fn,*p);,8.5动态存储分配,8.5.2free函数函数原型:voidfree(void*p)功能:释放由指针p指向的动态分配的内存区,以便再次被分配使用。说明:内存释放是指将p所指向内存单元的数据变成无效数据,p依然指向这块内存,为了防止该指针被继续使用,释放内存后应该及时将p指向NULL。,8.5动态存储分配,例8-15设计程序求一组学生的平均成绩,学生人数从键盘输入。问题分析:由于学生人数不确定,用于存放学生成绩的数组大小未知,故不能预先定义该数组,而应该在程序运行时根据键盘输入的学生人
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 邮储银行2025白银市秋招笔试英语题专练及答案
- 建设银行2025咸宁市秋招面试典型题目及参考答案
- 中国银行2025广州市秋招笔试性格测试题专练及答案
- 2025年3D打印技术的材料创新研究
- 交通银行2025淮安市信息科技岗笔试题及答案
- 2025私有云市场分析
- 农业银行2025河源市小语种岗笔试题及答案
- 交通银行2025内江市秋招笔试EPI能力测试题专练及答案
- 建设银行2025结构化面试15问及话术山西地区
- 农业银行2025三明市信息科技岗笔试题及答案
- 南亚环氧树脂
- 常见体表肿物
- 化疗所致恶心呕吐护理
- 信息检索技术讲义
- 商业银行基于华为OceanStor的关键业务同城切换方案
- 火力发电厂运煤设计规程
- 第十章DNA、RNA的生物合成ppt课件
- 3250变压器综合测试仪(共85页)
- 中国联通VI手册完整版
- 贾谊《鵩鸟赋》课件,《鵩鸟赋》讲解
- 翻转课堂视域下“导学案”的设计研究课题评审书
评论
0/150
提交评论