版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第八章综合设计与应用8.1.1变量的作用域变量可被识别、能够起作用的范围称为变量的作用域。变量作用域可以分为局部变量和全局变量。局部变量(LocalVariables)局部变量在语句块内定义的变量形参也是局部变量进入语句块时获得内存,仅能由语句块内语句访问,退出语句块时释放内存,不再有效说明:不同函数内的局部变量可以重名,它们是不同的变量,作用域不同,不会相互干扰若多个同名局部变量作用域重叠,则最内层复合语句中定义的局部变量有效局部变量举例(1)
floatfoo(intx){inta,i,j;/*局部变量*/...... /*只能用在foo内部*/}voidmain(){inta,b,c;/*局部变量*/......
/*只能用在main内部*/}x,a,i,j作用域a,b,c作用域不同函数内的局部变量可以重名例:不同函数中同名变量voidsub(){inta,b;a=6;b=7;printf("sub:a=%d,b=%d\n",a,b);}main(){inta,b;a=3;b=4;printf("main:a=%d,b=%d\n",a,b);sub();printf("main:a=%d,b=%d\n",a,b);}运行结果:main:a=3,b=4sub:a=6,b=7main:a=3,b=4局部变量举例(2)voidmain(){inta,b,i;......{intc,i;c=a+b;i=a-b;......}......}a,b,i作用域c,i作用域此范围内复合语句中定义的i有效多个同名局部变量作用域重叠全局变量(GlobalVariables)全局变量(外部变量)函数之外定义的变量说明作用域从变量定义处到本源程序文件结束若全局变量与局部变量重名,则局部变量在作用域内屏蔽全局变量自动初始化为0从程序运行起即占据内存,程序运行过程中可随时访问,程序退出时释放内存全局变量举例inta=10,b=5,x,y;
/*全局变量*/intmax(intx,inty){returnx>y?x:y;}intc;
/*全局变量*/voidmain(){inta=8;c=max(a,b);/*引用局部变量a*/}全局变量c作用域全局变量a,b,x,y作用域形参x,y作用域局部变量a作用域inta=3,b=5;max(inta,intb){intc;c=a>b?a:b;return(c);}main(){inta=8;printf("max=%d",max(a,b));}运行结果:max=8例:全局变量与局部变量#include
<stdio.h>intglobal; /*定义全局变量*/voidGlobalPlusPlus(void);main(){ global=1;
printf("BeforeGlobalPlusPlus(),itis%d\n",global); GlobalPlusPlus();
printf("AfterGlobalPlusPlus(),itis%d\n",global);}/*函数功能:对全局变量global加1,并打印加1之前与之后的值函数入口参数:无函数返回值:无*/voidGlobalPlusPlus(void){ printf("Before++,itis%d\n",global); global++;
printf("After++,itis%d\n",global);}#include
<stdio.h>voidGlobalPlusPlus(void);main(){ intglobal=1;
printf("BeforeGlobalPlusPlus(),itis%d\n",global); GlobalPlusPlus();
printf("AfterGlobalPlusPlus(),itis%d\n",global);}/*函数功能:对局部变量global加1,并打印加1之前与之后的值函数入口参数:无函数返回值:无*/void
GlobalPlusPlus(void){ intglobal=1; printf("Before++,itis%d\n",global); global++;
printf("After++,itis%d\n",global);}8.1.2变量的存储类别(1)存储类别的概念
变量的存储类别决定了变量的存储位置和存储方式。变量的存储位置有两个:内存的数据区和寄存器。内存中供用户使用的存储区,如表8-1所示。变量的存储方式也有两种:静态和动态。在程序运行时,变量的存储方式如表8-2所示。(2)存储类别的声明
声明变量的存储类别,一般是与声明变量的类型同时进行,方法是在变量的类型说明符前加上适当的存储类别说明符,每个变量只能有一种存储类别。一般形式:
存储类别说明符数据类型说明符变量名1,变量名2,…,变量名n;C语言中,变量有四种存储类别说明符。①自动存储类别(auto)②寄存器存储类别(register)③外部存储类别(extern)④静态存储类别(static)自动(auto)变量“自动”体现在进入语句块时自动申请内存,退出时自动释放内存动态局部变量标准定义格式auto类型名变量名;缺省的存储类型不初始化时,值是不确定的寄存器(register)变量寄存器CPU的内部容量很有限,但速度极快的存储器使用频率比较高的变量声明为register
,可以使程序更小、执行速度更快register类型名变量名;
例:registerinti;现代编译器有能力自动把普通变量优化为寄存器变量,并且可以忽略用户的指定,所以一般无需特别声明变量为registerexterninta;swap(){printf("%d",a);}#include<stdio.h>swap();inta=6;main(){swap();}main.cswap.c外部存储类别(extern)在定义点之前或在其他文件中引用,应进行如下声明:
extern类型名变量名;静态(static)局部变量一个函数的内部变量在函数退出后失效。再次进入函数,变量值重新初始化把此变量定义为static,则变量的值可以保存到下次进入函数staticinti;静态变量和全局变量都是静态存储类型自动初始化为0从静态存储区分配,生存期为整个程序运行期间但作用域不同静态局部变量举例intf(inta){intb=0;staticintc=3;b++;c++;returna+b+c;}voidmain(){intx=2,i;for(i=0;i<3;i++)printf("%d\n",f(x));}i0x2a2b0c3f(x)-121456789/*purpose:静态局部变量*/#include<stdio.h>intf(intnParam){
staticintnSum=1; /*静态局部变量*/ nSum=nSum+nParam; returnnSum;}voidmain(){ printf("%d\n",f(1)); printf("%d\n",f(1));}运行结果如图所示:8.2指针与数组8.2.1一维数组与指针指针也可当作数组名使用例:定义一个整型数组anArr,有10元素,采用数组名法实现对数组元素的键盘录入,并输出。
/* purpose:数组名法实现数组元素的录入与输出*/#include"stdio.h"#defineNUM5voidmain(){ intnArr[NUM],i; printf("inputelementsofnArr:");
for(i=0;i<NUM;i++) scanf("%d",nArr+i); for(i=0;i<NUM;i++)
printf("%-4d",*(nArr+i));}
运行结果如图所示:指针与二维数组一维数组a
a[1]
a[0][0]a[0][1]a[0][2]a[0][3]a[1][0]a[1][1]a[1][2]a[1][3]a[2][0]a[2][1]a[2][2]a[2][3]行地址列地址列地址列地址a[0]+0a[0]+1a[0]+2a[0]+3a[2]+0a[2]+1a[2]+2a[2]+3a[1]+0a[1]+1a[1]+2a[1]+3一维数组a[2]一维数组a[1]一维数组a[0]a[0]
a[2]
a+0
&a[0]
a+1
&a[1]
a+2&a[2]
指针与二维数组a----代表二维数组的首地址,第0行的地址
a+i----代表第i行的地址*(a+i)即a[i]----代表第i行第0列的地址*(a+i)+j即a[i]+j----代表第i行第j列的地址*(*(a+i)+j)即a[i][j]----代表第i行第j列的元素行地址转变成列地址指针与二维数组元素a[i][j]的地址的几种等价的引用方式&a[i][j]a[i]+j
*(a+i)+j
&(*(a+i))[j]元素a[i][j]的几种等价的引用方式a[i][j]*(a[i]+j)
*(*(a+i)+j)
(*(a+i))[j]8.2.2多维数组与指针(1)多维数组的地址表示――行地址与列地址。二维数组anArr的内存状态(2)用列指针访问二维数组元素
由于C语言中的二维数组元素是以行优先连续存储的,且在内存中元素的存储仍然是线性的,这一点从上图不难看出。因此可以定义一个指针变量pointer指向二维数组的第一个元素,那么i行j列元素的地址可表示为pointer+i*n+j,而元素的值为*(pointer+i*n+j),也可以使用pointer++这样的语句逐一访问二维数组的元素。例:定义一个整型数组anArr,2行2列,通过列指针变量输入与输出各元素的值。
#include"stdio.h"voidmain(){ intanArr[2][2]; int*pointer; pointer=anArr[0];/*pointer指向二维数组的第一个元素的地址*/ inti,j; printf("请输入各元素:"); for(i=0;i<2;i++) for(j=0;j<2;j++) scanf("%d",pointer+i*2+j); for(pointer=*anArr;pointer<*anArr+2*2;pointer++) printf("%4d",*pointer);}运行结果如图所示:(3)用行指针访问二维数组元素
为了便于访问二维数组,C语言中还专门设置了指向由n个元素组成的一维数组的指针。定义格式为:类型说明符(*指针名)[常量N]int(*p)[3];p=a;//用行地址初始化for(i=0;i<n;i++)
for(j=0;j<m;j++) printf("%d",*(*(p+i)+j));a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]pp++8.2.3指针数组
指针数组是一个数组,只不过数组中的元素都是相同的指针类型。其定义形式为:
[存储类型]数据类型*数组名[元素个数]
例:
int*pointer[5];pointer是一个有5个元素的数组,每个元素都是指向整型变量的指针。8.3函数main()中的参数带参数的主函数有什么特殊的意义吗?main()函数可以带多少个参数?其参数有何要求?命令行参数通过命令行参数,使用户可以根据需要来决定我们的程序干什么、怎么干?main(intargc,char*argv[])当你把main函数写成这样时argc的值为程序执行时参数的数目(包括命令本身)argv[X]为指向每个参数的字符指针这两个内设形参用于接收命令行参数
例:演示命令行参数与main函数各形参之间的关系
main(intargc,char*argv[]){
inti; printf("Theprogramnameis:%s\n",argv[0]);
if(argc>1) { printf("Theotherargumentsarefollowing:\n");
for(i=1;i<argc;i++) { printf("%s\n",argv[i]); } }}argv[0]echo.exeargv[1]argv[2]argv[3]programmingisfunptr指针数组字符串name8.4指针型函数
当一个函数的返回值是指针类型时,这个函数就是指针型函数。
指针型函数的一般定义形式为:函数类型*函数名([形参表]){
函数体}8.5动态存储空间分配动态存储空间分配相对于静态存储空间分配具有如下特点:①不需要预先分配存储空间;②分配的空间可以根据程序的需要扩大或缩小。C语言提供了若干动态存储空间分配函数,常用的有:malloc函数、calloc函数和free函数。(1)malloc()函数原型:void*malloc(unsignedintsize);头文件:#include<stdlib.h>参数:size――参数是一个无符号整形数,表示分配存储空间的字节数功能:在内存的动态存储区中分配一个长度为size的连续空间说明:若成功,返回指向分配区域起始地址的指针(类型为void);若失败,返回空指针NULL(2)calloc()函数原型:void*calloc(unsignedn,unsignedsize);头文件:#include<stdlib.h>参数:size――表示分配存储空间的字节数;
n――有多少个size功能:在内存的动态区存储中分配n个长度为size的连续空间说明:若成功,返回指向分配区域起始地址的指针(类型为void);若失败,返回空指针NULL(3)free()函数原型:voidfree(void*ptr);头文件:#include<stdlib.h>参数:ptr欲释放内存单元的地址功能:在完成对所分配内存空间的使用之后,要通过调用free()函数来释放它,释放后的内存区能够重新分配给其他变量使用说明:参数ptr必须是先前调用动态空间分配函数(malloc或calloc等)时返回的指针例:动态分配一块区域,存储一个学生数据,并输出该学生数据。
#include"stdio.h"#include"stdlib.h"structsStudent{ int nNum; char *cName; char cSex; float fScore;}*psStu;voidmain(void){
/*分配sizeof(structstu)字节空间,强制转换为stu类型,并把其首地址赋予指针变量pStu*/psStu=(structsStudent*)malloc(sizeof(structsStudent));
psStu->nNum=102;psStu->cName="Zhangping";psStu->cSex='M';psStu->fScore=62.5;printf("Number=%d\nName=%s\n",psStu->nNum,psStu->cName);/*输出空间数据*/printf("Sex=%c\nScore=%f\n",psStu->cSex,psStu->fScore);free(psStu); /*释放空间*/ }
运行结果如图:8.6链表8.6.1链表的概念问题:结构体内的成员类型可以是其本身吗?程序清单8-12
StuTest.c/*一个小测试*/#include"stdio.h"#include"stdlib.h"structstudent{ intnNum; charcName[20]; intnScoreAvg;
structstudentsStu;};voidmain(){printf("仅用来测试!");}
其编译结果如图:说明错误提示的意思为:用正在定义的student声明成员变量sStu有错误。这样,可以得到结论:结构体内的成员不可以用“自己”去定义。现在把上述结构体的定义做一点变化,代码如下图所示。structstudent{ intnNum; charcName[20]; intnScoreAvg; structstudent*sStu;};数据域指针域
再次进行编译,发现错误没有了,编译通过了,程序可以运行了。这是什么原因呢?
这个奇妙的指针可以指向什么样的内存单元呢?根据分析,可以得出:(1)链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表各结点指针域进行链接的。链表由一系列结点组成,结点可以在运行时动态生成。(2)链表中的每个结点通常由两个域组成,一个称为数据域data,另一个称为指针域next。数据域用来存储用户的数据,而指针域是一个结构体类型的指针,用来存储下一个结点的地址。结点的结构定义的一般形式为:
structnode{
数据类型data; structnode*next;};datanextheaddatanextdatanextdataNULL
链表原理图8.6.2链表的基本操作对链表的主要操作有:建立链表、查找链表、插入链表和删除链表等。下面定义一个学生结点,并据此进行详细介绍。
structstudent{ charcNum[10]; /*学号*/ floatfScore; /*成绩*/ structstudent*next; /*指针域*/};
structnode{intnum;structnode*next;}*p,*q,*r;main(){p=(structnode*)malloc(sizeof(structnode));q=(structnode*)malloc(sizeof(structnode));r=(structnode*)malloc(sizeof(structnode));p->num=10;q->num=20;r->num=30;p->next=q;q->next=r;printf("%d\n",p->num+q->next->num);}
A)10B)20C)30D)40EXERCISE1:
structnode{intnum;structnode*next;}*p,*q,*r;main(){p=(structnode*)malloc(sizeof(structnode));q=(structnode*)malloc(sizeof(structnode));r=(structnode*)malloc(sizeof(structnode));p->num=10;q->num=20;r->num=30;p->next=q;q->next=r;printf("%d\n",p->num+q->next->num);}A)10B)20C)30D)40
p
q
r
102030EXERCISE2:有以下结构体说明和变量定义,如图所示,指针p、q、r分别指向此链表中三个连续结点。structnode{intdata;structnode*next;}*p,*q,*r;现要将q所指结点从链表中删除,同时保持链表的连续,以下不能完成指定操作的语句是()A)p->next=q->next;B)p->next=p->next->next;C)p->next=r;D)p=q->next;1.建立链表例8-11编写一个create()函数,按照规定的学生结点结构,创建一个学生成绩链表。首先向系统申请一个结点的空间,然后向数据域输入信息(学号cNum、成绩fScore),并将指针域置为NULL(链尾标志),最后将新结点插入到链表尾,完成链表的建立过程,需要用到3个指针变pHead、pNew、pTail。
解决方案(1)pHead──头指针变量,指向链表的第一个结点,用作函数返回值。由于单链表中每个结点的存储地址存放在其前趋结点next域中,而开始结点无前趋,故应让头指针head指向开始结点。链表可以由头指针唯一确定,因此用Create()函数建立完链表后,应该返回链表的头指针。(2)pNew──指向新申请的结点。(3)pTail──指向链表的尾结点,可用pTail->next=pNew实现将新申请的结点插入到链表尾,使之成为新的尾结点。根据上述,建立链表流程如图8-26所示。如果输入的学号为0,表示链表建立完毕。
为了验证链表建立的正确性,还需要一个链表顺序输出功能,由函数Display()实现,功能是从头到尾依次输出链表各结点的数据域。参数为头结点指针pHead。实现流程如图8-27所示。程序清单8-13
CreateLinkList.c/*定义学生结点结构*/structstudent{ charcNum[10];/*学号*/ floatfScore; /*成绩*/ structstudent*next; /*指针域*/};程序清单8-13
CreateLinkList.cstructstudent*Create(){ structstudent*pHead=NULL,*pNew,*pTail; intnCount=0; /*链表中的结点个数(初值为0)*/ while(1) { pNew=(structstudent*)malloc(LEN); /*申请一个新结点的空间*/
/*1、输入结点数据域的各数据项*/ printf("InputthenumberofstudentNum.%d(9bytes):",nCount+1); scanf("%9s",pNew->cNum); if(strcmp(pNew->cNum,"0")==0)/*如果学号为0,则退出*/ { free(pNew);/*释放最后申请的结点空间*/ break; /*结束while循环*/ }程序清单8-13
CreateLinkList.cprintf("InputtheScoreofthestudentNum.%d:",nCount+1); scanf("%f",&pNew->fScore); nCount++;/*结点个数加1*/
/*2、置新结点的指针域为空*/ pNew->next=NULL;
/*3、将新结点插入到链表尾,并设置新的尾指针*/ if(nCount==1) pHead=pNew; /*是第一个结点,置头指针*/ else pTail->next=pNew; /*非首结点,将新结点插入到链表尾*/ pTail=pNew; /*设置新的尾结点*/ } returnpHead;}程序清单8-13
CreateLinkList.cvoidDisplay(structstudent*pHead){ structstudent*p; p=pHead; /*指向头结点*/ printf("学号\t\t成绩\n"); while(p!=NULL) /*循环输出*/ { printf("%s\t",p->cNum); printf("%.1f\n",p->fScore); p=p->next; /*指向下一个结点*/
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- ICU休克患者营养支持护理效果评价
- 2026年安徽省皖能聚合智慧能源有限公司所属子公司会计岗位社会公开招聘考试备考试题及答案解析
- 2026年南平武夷山市医疗卫生单位第九届“人才·南平校园行”紧缺急需人才招聘8人考试备考题库及答案解析
- 2026广西南宁市兴宁区第一初级中学招聘笔试备考试题及答案解析
- 2026国网辽宁省电力有限公司招聘140人(第二批)笔试参考题库及答案解析
- 2026年双鸭山饶河县公益性岗位招聘34人笔试参考题库及答案解析
- 2026年江西水利职业学院单招职业适应性测试题库有答案解析
- 2026陕西君保融数字产业有限公司招聘(47人)笔试备考题库及答案解析
- 2026新疆图木舒克市商砼站招聘1人考试参考题库及答案解析
- 2026湖南怀化沅陵县招聘青年就业见习生21人笔试备考试题及答案解析
- 《PLC电气控制技术》课件(共九章)
- 智能小车项目课件
- 基于AI大模型的金融数据中心智能网络运维应用研究报告
- 新空间经济学新经济地理学讲课文档
- 2025年黑龙江护理高等专科学校单招职业技能考试题库及答案解析
- 医用加速器等中心检测:新方法探索与误差深度剖析
- DB43∕T 2512-2022 森林火灾无人机勘测技术规范
- 【《基于西门子S7-200 PLC的鸡舍环境监控系统设计》13000字(论文)】
- 传播学研究方法 课件全套 ch1-导论-传播学研究方法的发展历程 -ch18-大数据的分析与可视化-用图表勾勒网络关系
- 急性上消化道出血病例讨论
- 非遗文化融入高职院校美育建设的策略与实践
评论
0/150
提交评论