资源描述
第六章复合数据类型,6.1指针类型概念:旅馆房间、房间编号、房间名称、派房牌(上写房间号)。1)地址给内存单元(一般是字节)的编号。计算机根据它找到对应的字节进行访问(存取)。高级语言中定义一个变量,编译时根据其类型分配相应数目的字节(如int型分2个字节,float分4个字节),将变量名与对应内存字节映射。变量名地址内存单元2)指针给变量、数组、结构体、函数等分配的内存单元或块区的首地址。假如有:longm=56000则:main()inta,b;scanf(%d%d”,2000H,2001H,2EA0H,2EA1H,a=10,b=8,内存,地址,变量,10,8,指针变量,p2=例int*p1,*p2;2)指针变量的赋值指针变量=,其中:*号是取值运算符。*与定义时的*与使用时的*含义不同,前者表示定义的是指针变量;后者是对变量的取值运算。定义了一个某类型的指针变量后,它可以指向任意一个同类型变量。4)指针变量作函数参数主调函数被调函数实参形参一般要求:只有定义为静态或外部存储的才能初始化。三、数组作为函数的参数(传递地址)例:对一字符串反序输出。(exinver.c)四、二维数组的声明形式:类型数组名常量表达式常量表达式;如:intscores503;说明:编译程序为二维数组分配存储空间时是按行进行的,即先按顺序存放第一行的所有数据,然后接着按顺序存放第二行的所有数据,如此类推。二维数组scores的存储空间分配如下图所示:,.25000scores0025002scores0125004scores0225006scores1025008scores1125010scores12.25298scores492.,五、二维数组元素的引用与初始化引用形式:数组名行下标列下标/下标为整数类型的表达式如:scores201=100;初始化形式:存储类别数据类型数组名常量1常量2=初值;如:staticints34=50,60,80,20,40,90,70,100,10;例矩阵行列互换。Exmatrix.c123415956782610910111237114812六、指针与数组在语言中,指针与数组之间的关系是十分密切的。指针类型变量可以当作数组使用,数组类型变量也可以当作指针使用,即在语,言中,我们可以象访问指针一样访问数组,也可以象访问数组一样访问指针。其区别为:数组名不能自加、自减,但指针变量可以。例如:inta10,*p;p=a;p+或p-都是成立的,而a+或a-是不成立的。而*(a+I)、aI、*(p+I)、pI是等价的。七、指针数组与数组指针指针数组:指基类型为指针类型的数组,即该数组的每个元素均为一个指针。如果我们需要保留许多指针的值,也就是要保存多个变量的地址,就可以使用指针数组。定义形式:数据类型*数组名数组长度;如:int*p10;/在此声明了一个包含10个整数类型指针变量的数组p。这里*并不是数组名字的组成部分,它只是告诉编译程序p是一个整数类型的指针数组,而不是简单的整数类型数组。,例:建立如下距阵并输出1000101010001000101010001程序为:main()inta55=0,*p5,i,j;for(i=0;i”引用。例如:sum=st1.score+st2.score;成员运算符(多级)例如:age=1999-st1.birthday.year;_QC允许将一结构体变量的所有分量赋予同类的另一变量。例如:st2=st1;例ex2stu1.c,四、结构体数组,以某结构体类型也可以定义数组例按姓名查询。ex2stuarr.c,structstudentintnum;charname30;charsex;floatscore;stu30;每个下标变量stui都有结构体类型student的各个分量;下标变量的引用同变量。,五、结构体类型的指针,指向结构体类型变量的指针,指向结构体类变量的指针就是该变量所占用的内存区段的首址。例structstudentintnum;charname3;charsex;floatscore;st1,st2,st3;structstudent*p=,num,name,sex,score,:,:,2A00H,st1,p,指向结构体类型数组的指针,指向结构体类数组的指针就是该数组所占用的内存区段的首址。例structstudentintnum;charname3;charsex;floatscore;st30=;structstudent*p=st;for(p=st;pnum,p-name,p-sex,p-score);,:,:,2A00H,st0,st1,st2,st3,:,2A0AH,2A14H,2AE0H,p,例:若干个学生的信息包括:学号、姓名、三门可课的成绩(c语言、电子技术、控制理论)、总分,要求打印一份名次表。分析:总分是需要计算的。按总分从小到大排序(bubble)。按行输出。Ex2table.c,指向结构体类型数据的指针一、指向结构体类型变量的指针例打印通讯录。(excommu.c)二、指向结构体数组的指针例用结构指针建立一个图书检索系统。按书名检索。(exsearch.c)三、结构指针的使用例链表。链表的建立、遍历、查找、插入、删除操作。,2020/5/3,链表,什么是链表?,线性表:有限个元素的有序集合。可用数组或链表表示。数组和链表两者都逻辑连续,但后者可以在空间不连续。动态数据结构:其大小可变;动态分配存储空间。链表是最简单的一种,属于线性动态数据结构,树是非线性动态数据结构。链表:链表中的一个元素称为一个结点或节点。每个结点由两部分组成:数据部分、指向上下结点的指针。靠这样的指针把各个结点串联起来构成链表。分单向、双向链表,后者可以两方向连接。,0,0,单向链表,双向链表,0,数据部分,2020/5/3,链表,为什么使用链表?,1)不需要连续存储空间,可利用内存碎片;2)插入删除元素不需移动其它元素,处理速度快;3)动态分配存储空间,不必以最大可能长度预定存储空间,且可以随意扩充表的容量。动态分配存储空间(使用函数)void*malloc(unsignedsize)函数(memoryallocation):在内存的动态存储区中分配一个长度为size的连续空间,size为结点元素各成员项的总字节数,可以用sizeof(数据类型名)运算符获得。该函数的返回值是一个指针,它的值是所分配存储区的起始地址,当该函数未成功执行时,返回值为0。如:structstudentintnum;floatscore;structstudent*next;*p1;p1=(structstudent*)malloc(sizeof(structstudent);,voidfree(ptr)函数:该函数释放由ptr指向的内存区。Ptr是最近一次调用calloc或malloc函数时返回的值。用结构体及结构体指针构造链表和链表操作(1)建立链表。链表的建立过程可以描述如下:假设结构体定义如下:structnodeintnum;floats;structnode*next;1.为了建立链表,在程序中需要使用两个指向结构的指针。例如:structnode*p1,*p2;建立链表时,首先使用malloc函数为第一个元素分配存储空间,并把该空间的地址赋予p1,使p1指向该存储空间:p1=(structnode*)malloc(sizeof(structnode);,2.把p1的值赋予p2,从而使p2也指向该存储空间,便于连接后面的结点元素。3.通过p1访问成员num和s,并对其赋值:p1-num=1;scanf(“%f”,使指针p2指向第二个(始终指向最后一个)元素。反复执行上面的四个语句,就可以不断地把元素加入到链表中去。这种建立链表的方法是从表头插入的过程,指针p2总是指向最后出现的那个元素。,链表建立函数:#defineNULL0/*定义空指针,作为表尾结点的next域*/structnode/*结点元素的数据结构类型*/intnum;structnode*next;intn=0;/*定义外部变量n,用来记录结点的个数*/structnode*creat()/*函数的返回值为指向头结点的指针*/structnode*p1,*p2,*head;p2=NULL;/*最先加入的为表尾结点,将其next域置为NULL*/printf(npleaseinputnum:n);dop1=(structnode*)malloc(sizeof(structnode);/*申请一个结点空间*/,scanf(%d,/*返回链表头指针*/,(2)链表的遍历(输出)函数如下:voidprint(head)structnode*head;structnode*p;printf(nThetableis:n);p=head;/*以表尾结点中指针为NULL做为遍历结束的标志*/while(p!=NULL)printf(%4d-%7.2f,p-num,p-s);p=p-next;/*移向下一个结点*/(link_t.c),2020/5/3,链表,插入结点删除结点,0,单向链表,2100h,2100h,2180h,2010h,2050h,2050h,2a02h,2a02h,2100h,2180h,0,单向链表,2100h,2050h,2a02h,2010h,2050h,2100h,2a02h,2a02h,指针在函数中的应用一、指针作为函数的参数用指针作为函数的参数,应该在主调函数和被调用函数分别定义指针变量;在函数调用中实参指针和形参指针类型应一致。例分析结果。(expoint.c)#includestdio.h”sub(int*s,inty)staticintt=3;y=st;st=st+4;t-;main()inta=1,2,3,4,i,x=0;printf(xain);for(i=3;i=0;i-)sub(a,x);printf(%d%dn,x,ai);,Xai08070605,二、函数的指针及函数的指针变量概念函数的指针就是函数代码在内存中所占存储区的首地址。函数的指针变量(指向函数的指针变量)存放函数的指针,用来指向某函数。p+,p+n无意义。可以在不同时间用同一个指针变量调用不同函数。指向函数的指针变量的定义类型标示符(*变量名)();例如:float(*p)();表示p是一个指向返回值为float型的函数的指针变量。运用例求n!。赋值形式:=;调用形式:(*指向函数的指针变量)(实参表);(expfun.c),#includestdio.hintadd(n)intn;intsum=1,i;for(i=1;i2)strcpy(oldname,argv1);strcpy(newname,argv2);elseprintf(use:jc12oldnamenewnamen);exit(1);if(rename(oldname,newname)=0)puts(successfuln);exit(0);elseprintf(nerrorn);exit(2);return(0);exren.c,定义在dir.h中,系统函数,指向结构体类型数据的指针一、指向结构体类型变量的指针例打印通讯录。(excommu.c)二、指向结构体数组的指针例用结构指针建立一个图书检索系统。按书名检索。(exsearch.c)三、结构指针的使用例链表。链表的建立、遍历、查找、插入、删除操作。,2020/5/3,枚举类型,Madebylut,共用体类型,位域,类型别名,2020/5/3,共用体(联合)类型,什么是共用体,结构型数据类型;存储形态:共用体类型变量的若干分量分时共占同一存储空间。例如:uniondatainti;charc;longl;com;com.i=10;com.c=A;com.l=65535;,00000000000000001111111111111111,01000001,2020/5/3,共用体类型,共用体类型及其变量的定义和引用,共用体类型及其变量的定义和引用与结构体类似,本质的不同在于使用内存的方式。类型定义:union类型名数据类型变量名;数据类型变量名;联合变量名表;(或;结束)变量的定义:三种方式(同结构提变量的定义方式)共用体变量的引用方式:(.或-)如前所示:com.I、com.c、com.l,例1main()unionunsignedcharc;unsignedintI4;z;z.I0=65;z.I1=66;printf(“%cn”,z.c);结果:A,例2main()unionintI2;longk;charc4;r,*s=结果:9,570560,0123,9,8,S-I0,S-I1,S-c0,2020/5/3,枚举类型什么是枚举类型,枚举是一组命名的整数常量,用以说明可能类型变量的所有合法值。定义类型形式:enum名字枚举列表变量表;定义变量形式(三种方式)枚举类型的变量仅有几个确定的值。例如:enumweekdaysun,mon,tue,wed,thu,fri,satworkday;枚举元素是常量,具有数值。按顺序默认为0,1,2,.;也可以在定义时按需求指定。如:enumcolorred,green,blue=8,blank,white;,应用举例例1main()enumlanguagebasic=3,assembly,ada=100,cobel,fortran97;enumlanguagespeak;speak=fortran97;printf(“%dn”,speak);结果:102,例2main()enumteammy,your=4,his,her=his+10;printf(“%d%d%d%dn”,my,your,his,her);结果:04515,类型别名,为提高程序的可读性,我们可用保留字typedef为类型起一个新名字,这个新名字应该用一个有意义的标识符来命名。typedef不建立新的类型,它只是为原有类型起一个新的名字而已。如:typedefchar*STRING;就可以用STRING代替char*,即STRINGP;定义了一个指向字符的指针变量p。例1:typedefunionlongI;intk5;charc;DATE;/10structdate/2+10+8=20intcat;DATEcow;doubledog;too;,main()DATEmax;printf(%dn”,sizeof(structdate)+sizeof(max);结果:30例2typedefunionlongx2;inty4;charz8;MYTYPE;MYTYPEthem;main()printf(%dn”,sizeof(them);结果:8,位域,所谓的位域是以位为单位定义长度的结构体类型中的成员。位域类型及变量的定义形式:struct位域类型名类型位域名1:长(二进制位数);类型位域名2:长(二进制位数);变量表;注:一个位域可以定义成int,unsigned或signed。长度为1的位域必须定义为unsigned,因为单个位不可能有符号。,位域的引用:structpacked_dataunsigneda:2;unsignedb:6;unsignedc:4;unsignedd:4;inti;data;,abcdi,264416,例1:下列定义中的错误。StructtwobyteunsignedI:3;unsignedj:4;unsigned:0;floatk:4;unsigned:2unsignedm:18;bit;,例2:main()structppunsignedi:3;unsignedj:4;unsignedk:4;unsigned:0;/下面将从下一字节开始分配unsigned:3;unsignedm:6;unionuu/长度为4个字节structppbb;longintl;u;u.l=0 x12345678;,printf(%u,%u,%u,%u,%dn,u.bb.i,u.bb.j,u.bb.k,u.bb.m,sizeof(structpp);结果:0,15,12,6,4,
展开阅读全文