版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
8.1結(jié)構(gòu)1.結(jié)構(gòu):是擁有若干分量的一種構(gòu)造類型,而且一個結(jié)構(gòu)的分量可以有不同的類型,包括指針、數(shù)組、其它結(jié)構(gòu)。2.定義:struct
結(jié)構(gòu)類型名
{成員列表};第八章結(jié)構(gòu)和聯(lián)合例:struct
date{unsignedyear;
unsignedmonth;unsignedday;};yearmonthday注:不帶變量的結(jié)構(gòu)說明不占存儲空間,結(jié)構(gòu)類型集中放到一個文件中,需要時用#include3.三種定義結(jié)構(gòu)變量的方法1)先定義結(jié)構(gòu)類型,再定義結(jié)構(gòu)變量struct
date{unsignedyear;
unsignedmonth;
unsignedday;};struct
dated1,d2yearmonthdayd1yearmonthdayd22)在定義結(jié)構(gòu)類型的同時定義變量struct
date{unsignedyear;
unsignedmonth;
unsignedday;}d1,d2;3)直接定義結(jié)構(gòu)類型變量struct{unsignedyear;
unsignedmonth;
unsignedday;}date,d1,d2;3.三種定義結(jié)構(gòu)變量的方法struct
student{intnum;
charname[20];
charsex;
intage;
struct
datebirthday;charaddr;}student1,student2;4.結(jié)構(gòu)的嵌套struct
date{unsignedyear;unsignedmonth;unsignedday;};numnamesexagebirthdayyearmonthdayaddr8.2訪問結(jié)構(gòu)成員舊標(biāo)準(zhǔn)規(guī)定只能對結(jié)構(gòu)變量中的成員分別訪問,而不能對結(jié)構(gòu)變量進行賦值和輸出。新標(biāo)準(zhǔn)允許將一個結(jié)構(gòu)變量直接賦給另一個具有相同結(jié)構(gòu)的結(jié)構(gòu)變量。如果結(jié)構(gòu)變量本身又屬于一個結(jié)構(gòu)類型,只能對最低層的成員進行賦值、存取和運算。如:
student1.birthday.year=1967;“.”是成員(分量)運算符,優(yōu)先級最高,自左向右結(jié)合。
結(jié)構(gòu)成員可以象普通變量一樣進行各種運算,例如:
student2.age=student1.age;
student1.age++;++studdent2.age;
可以引用成員的地址,結(jié)構(gòu)變量的地址,例如:&
student1.num&student18.2訪問結(jié)構(gòu)成員當(dāng)結(jié)構(gòu)變量為全局變量或靜態(tài)變量時,可在定義時初始化,例如:static
struct
student{intnum;
charname[20];charsex;charaddr[20];}a={54,“Jane”,“
M
”,“
123Road
”};8.2訪問結(jié)構(gòu)成員8.3結(jié)構(gòu)數(shù)組和指向結(jié)構(gòu)的指針當(dāng)結(jié)構(gòu)中的每一個元素都是同一結(jié)構(gòu)類型時,稱該數(shù)組為結(jié)構(gòu)數(shù)組。定義結(jié)構(gòu)數(shù)組時,可對全局或靜態(tài)存儲類別的數(shù)組初始化。structstudent{intnum;charname[20];
intage;charaddr[30];}stu[]={{10101,“LiLin”,18,“M”,“beijing”},
{10102,“FuPing”,19,“M”,“shanghai”}};numnamesexageaddr10101LiLinM18beijing10102FuPing19shanghaiMstustructstudent{intnum;charname[20];
intage;charaddr[30];}stu[]={{10101,“LiLin”,18,“M”,“beijing”},
{10102,“FuPing”,19,“M”,“shanghai”}};8.3結(jié)構(gòu)數(shù)組和指向結(jié)構(gòu)的指針struct
value{intkey;
intfreq;};#defineARRAYSIZE1000;staticstruct
valueset_arr[ARRAYSIZE];find(x)intx{inti,m;set_arr[m=set_arr[0].freq+1].key=x;set-arr[m].freq=0;for(i=1;set-arr[i].key!=x;i++);set-arr[i].freq++;if(i==m)set-arr[0].freq++;}例8.1在某集合中查詢是否存在值x,若不存在,則將x加入集合中。每次查詢均記錄查詢的頻率。keyfreqset-arr[0]set-arr[i]set-arr[m]x0
x
freq++字符個數(shù)指向結(jié)構(gòu)的指針:用一個指針變量指向結(jié)構(gòu)變量,此時該指針變量的值是結(jié)構(gòu)變量的起始地址。指針變量也可以用來指向結(jié)構(gòu)數(shù)組中的元素。例如:
struct
studentstu_1;
/*定義結(jié)構(gòu)變量*/struct
student
stu[4];/*定義結(jié)構(gòu)數(shù)組*/struct
student
*p;
/*定義指向結(jié)構(gòu)的指針變量*/p=&stu_1;
/*指向結(jié)構(gòu)變量stu_1*/p=stu;
/*指向結(jié)構(gòu)數(shù)組stu*/8.3結(jié)構(gòu)數(shù)組和指向結(jié)構(gòu)的指針structstudent{intnum;charname[20];charsex;floatscore;};通過指向結(jié)構(gòu)的指針訪問結(jié)構(gòu)成員,訪問結(jié)構(gòu)成員的方式:結(jié)構(gòu)變量名.成員名例如:stu_1.num;(*p).num;/*(*p)表示p指向的結(jié)構(gòu)變量,注意*p兩側(cè)的括號不能省略,因為成員運算符的優(yōu)先級高于取內(nèi)容運算符的優(yōu)先級。(*p).num:p指向的結(jié)構(gòu)變量中的成員num。通過指針變量訪問結(jié)構(gòu)成員的一般形式是:指向結(jié)構(gòu)的指針變量->成員名注意“.”和“->”的優(yōu)先級相同,自左向右結(jié)合。例如:p->num;stu_1.num;(*p)
.num;含義相同。8.3結(jié)構(gòu)數(shù)組和指向結(jié)構(gòu)的指針請分析以下幾種運算:p->n;得到p指向的結(jié)構(gòu)變量中成員n的值。
p->n++;得到p指向的結(jié)構(gòu)變量中的成員n的值,用完該值后使它加1。++p->n;得到p指向的結(jié)構(gòu)變量中的成員n的值使之加1。如果p指向結(jié)構(gòu)數(shù)組的某個元素,那么,(++p)->num;取下一個數(shù)組元素的成員num的值。(p++)->num取數(shù)組元素的成員num的值,然后將p指向下一個數(shù)組元素。(
)(
)如果指針p已定義為指向struct
student類型的數(shù)據(jù),它只能指向一個結(jié)構(gòu)類型數(shù)據(jù)。p的值是stu數(shù)組的一個元素的起始地址。不是指向一個數(shù)組元素中的某一成員,即p的地址不能是成員的地址。例如:p=&stu[2].num;/*是不對的*/8.3結(jié)構(gòu)數(shù)組和指向結(jié)構(gòu)的指針
例8.2在UNIX系統(tǒng)中用結(jié)構(gòu)數(shù)組sptmap來記錄系統(tǒng)頁表空間??梢赃@樣簡單理解:數(shù)組sptmap的每一個元素記錄一片連續(xù)的可用空間,其成員分別表示可用空間的首地址和長度,結(jié)構(gòu)如下:struct
map{shortm_size;/*長度*/
unsignedshortm_addr;/*地址*/}sptmap[100];從sptmap[1]開始搜索sptmap,sptmap[0].m-addr=0sptmap[0].m-size=整個stpmap表中未用的map數(shù),初始化時將未用表項的成員m-size置0。8.3結(jié)構(gòu)數(shù)組和指向結(jié)構(gòu)的指針m-addrm-sizesptmap[100]0表中未用的map數(shù)0102401023102420472048304730485047504810242048100030482000#definemapstart(x)&x[1]#definemapsize(x)x[0].m-sizemalloc(mp,size)structmap*mp;unsignedsize;{registerunsignedinta;registerstructmap*bp;for(bp=mapstart(mp);bp->m-size;bp++){if(bp->m-size>=size){a=bp->m-addr;
bp->m-addr+=size;
if((bp->m-size-=size)==0){do{bp++;
(bp-1)->m-addr=bp->m-addr;
}while((bp-1)->m-size=bp->m-size);
mapsize(mp)++;}
return(a);}}return(0);}1.sizeof():“求字節(jié)數(shù)”運算符,其優(yōu)先級別與++、--等運算符相同。sizeof的運算對象:數(shù)據(jù)類型,返回值:該類型數(shù)據(jù)在內(nèi)存中占用的字節(jié)數(shù)量。例如:sizeof(int),
sizeof(double*),
sizeof(structstudent)等等。2.malloc函數(shù):以一個無符號整數(shù)作為參數(shù),返回指向字符的指針,例如:char*p;p=malloc(10);從可用空間中分配連續(xù)10個字節(jié)的存儲空間,返回該片存儲空間的首地址。如果沒有足夠的可用空間,則返回一個空指針NULL用以表明分配空間失敗。8.4sizeof運算符和C的動態(tài)存儲分配函數(shù)3.free(p):p是一個指針,free將p所指向的存儲空間歸還給系統(tǒng)。執(zhí)行free(p)后,不會變更指針變量p的值,這個指針仍然指向原來的存儲空間。若p和q是兩個指向同一地址的指針變量,則執(zhí)行free(p);后,應(yīng)該跟有如下語句:
p=q=NULL;例如:int*pi;char*pc;語句*pc=‘a(chǎn)’;是錯誤的。因為pc的初值不確定??梢园涯硞€變量的地址賦給pc,或用malloc函數(shù)為它動態(tài)地分配存儲空間:pc=malloc(1);為安全起見,調(diào)用malloc時應(yīng)該判斷是否成功地分配了存儲空間。形式如下:if((pc=malloc(1))==NULL)假設(shè)調(diào)用malloc分配了位置是10的一個存儲單元,則語句*pc=‘a(chǎn)’;8.4sizeof運算符和C的動態(tài)存儲分配函數(shù)#include“stdio.h”#defineINTSIZEsizeof(int)#defineNODESIZEsizeof(int)+sizeof(char*)#defineERROR{printf(“error\n”);return;}main(){inti;char*p,*q,*first,*malloc();
if((p=malloc(NODESIZE))==NULL)ERROR
first=p;*(int*)p=1;p+=INTSIZE;for(i=2;i<10;i++,p+=INTSIZE)
if((q=malloc(NODESIZE))==NULL)ERROR
else{*(char**)p=q;p=q;*(int*)p=i;}*p=NULL;for(p=first;p;p+=INTSIZE,p=*(char**)p)
printf(“%d”,*(int*)p);putchar(‘\n’);}例8.3建立一個從1到9的整數(shù)鏈表,然后打印出這些值。P=malloc(sizeof(int)+sizeof(char*))*(int*)p=1p+=sizeof(int)*(char**)p=(q=malloc(sizeof(int)+sizeof(char*)))****(int*)p=2p+=sizeof(int)*(int*)p=8p+=sizeof(int)*(char**)p=(q=malloc(sizeof(int)+sizeof(char*)))****(int*)p=9NULL函數(shù)之間結(jié)構(gòu)體變量的數(shù)據(jù)傳遞向函數(shù)傳遞結(jié)構(gòu)體變量的成員作為成員變量(簡單變量、數(shù)組或指針變量),它們可以參與所屬類型允許的任何操作;向函數(shù)傳遞結(jié)構(gòu)體變量新的ANSIC標(biāo)準(zhǔn)允許把結(jié)構(gòu)體變量作為一個整體傳送給相應(yīng)的形參;傳遞的是實參結(jié)構(gòu)體變量的值;系統(tǒng)將為結(jié)構(gòu)體類型的形參開辟相應(yīng)的存儲單元,并將實參中各成員的值賦給對應(yīng)的形參成員。8.5結(jié)構(gòu)作為函數(shù)的參數(shù)結(jié)構(gòu)體變量作為實參傳遞給函數(shù),對應(yīng)形參得到的是它的值;函數(shù)體內(nèi)對形參結(jié)構(gòu)體變量中任何成員的操作,都不會影響對應(yīng)實參中成員的值;保證了調(diào)用函數(shù)中數(shù)據(jù)的安全;限制了將運算結(jié)果返回給調(diào)用函數(shù)。8.5結(jié)構(gòu)作為函數(shù)的參數(shù)8.5結(jié)構(gòu)作為函數(shù)的參數(shù)在舊標(biāo)準(zhǔn)中,在結(jié)構(gòu)上可以執(zhí)行的操作僅有用&來取得它的地址,和引用它的成員。指向結(jié)構(gòu)的指針變量卻不受這些限制,從而使結(jié)構(gòu)和函數(shù)仍能在一起協(xié)調(diào)工作。函數(shù)的返回值是結(jié)構(gòu)體類型;函數(shù)可以返回指向結(jié)構(gòu)的指針;用指向結(jié)構(gòu)的指針變量作參數(shù)。傳遞結(jié)構(gòu)體的地址:將結(jié)構(gòu)體變量的地址作為實參傳遞對應(yīng)的形參應(yīng)該是一個基類型相同的結(jié)構(gòu)體類型指針;系統(tǒng)只需為形參指針開辟一個存儲單元存放實參結(jié)構(gòu)體變量的地址值,而不必另行建立一個結(jié)構(gòu)體變量;通過函數(shù)調(diào)用,有效地修改結(jié)構(gòu)體中成員的值節(jié)省時間、提高效率。8.5結(jié)構(gòu)作為函數(shù)的參數(shù)例:通過函數(shù)給結(jié)構(gòu)體成員賦值structst{chars[10];
intt;}getdata(struct
st
*p){scanf(“%s%d”,p->s,&p->t);}main(){struct
st
a;
getdata(&a);
printf(“%s,%d\n”,a.s,a.t);}8.5結(jié)構(gòu)作為函數(shù)的參數(shù)函數(shù)的返回值是結(jié)構(gòu)體類型,例:struct
st
{inta;charb;}structstfun(struct
st
x){x.a=99;x.b=‘S’;returnx;}main(){struct
st
y;y.a=0;y.b=‘A’;
printf(“y.a=%dy.b=%c\n”,y.a,y.b);
y=fun(y);
printf(“y.a=%dy.b=%c\n”,y.a,y.b);}8.5結(jié)構(gòu)作為函數(shù)的參數(shù)運行結(jié)果:y.a=0y.b=Ay.a=99y.b=S函數(shù)的返回值可以是指向結(jié)構(gòu)體變量的指針,例:struct
st
{inta;charb;}structst
*fun(struct
st
x){struct
st
*px
x.a=100;x.b=‘C’;px=&x;returnpx;}main(){struct
st
y,*p;
y.a=999;y.b=‘X’;printf(“y.a=%dy.b=%c\n”,y.a,y.b);
p=fun(y);printf(“(*p).a=%d(*p).b=%c\n”,(*p).a,p->b);}8.5結(jié)構(gòu)作為函數(shù)的參數(shù)運行結(jié)果:y.a=999y.b=X(*p).a=100(*p).b=C例如:structstudent{longnum;charname[20];};一個返回結(jié)構(gòu)指針的函數(shù)
structstudent*new(){structstudent*aux;aux=(structstudent*)malloc(sizeof(structstudent));if(aux==NULL)
printf(“Outofmemory\n”);return(aux);}8.5結(jié)構(gòu)作為函數(shù)的參數(shù)也可以把此函數(shù)寫成傳遞一個指向結(jié)構(gòu)的指針的指針作參數(shù)的函數(shù)。
voidnew1(s)
struct
student**s;{struct
student*aux;
aux=(struct
student*)malloc(sizeof(struct
student));if(aux==NULL)
printf(“Outofmemory\n”);else*s=aux;}8.5結(jié)構(gòu)作為函數(shù)的參數(shù)利用結(jié)構(gòu)體變量構(gòu)成鏈表結(jié)構(gòu)體中含有可以指向本結(jié)構(gòu)體的指針成員結(jié)構(gòu)體的自引用:當(dāng)一個結(jié)構(gòu)體中有一個或多個成員是指針,它們的基類型就是本結(jié)構(gòu)體類型時,通常把這種結(jié)構(gòu)體稱為可以“引用自身的結(jié)構(gòu)體”。例如:struct
link{charch;
struct
link
*p;}a;8.6結(jié)構(gòu)的自引用a.ch
a.p
鏈表:把同一類型的結(jié)構(gòu)體變量“鏈接”到一起形成“鏈表”;結(jié)點:被連接在一起的結(jié)構(gòu)體變量;靜態(tài)鏈表:由系統(tǒng)在內(nèi)存中開辟了固定的、互不連續(xù)的存儲單元,在程序執(zhí)行的過程中,不可能人為地再產(chǎn)生新的存儲單元,也不可能人為地使已開辟的存儲單元消失。8.6結(jié)構(gòu)的自引用0f04100f0C200f1430NULL0f000f020f040f060f080f0A0f0C0f0E0f100f120f140f16ha.cha.pb.chb.pc.chc.p例:一個簡單的鏈表struct
node{intdata;
struct
node
*next;}main(){structnodea,b,c,*h,*p;a.data=10;b.data=20;c.data=30;
h=&a;a.next=&b;b.next=&c;c.next=‘\0’;
p=h;while(p){printf(“%d”,p->data);
p=p->next;}
printf(“\n”);}8.6結(jié)構(gòu)的自引用abc102030h\0ppp動態(tài)鏈表:鏈表中的每個存儲單元都由動態(tài)存儲分配函數(shù)獲得。各次動態(tài)分配的存儲單元地址不連續(xù);各數(shù)據(jù)之間存在著接序關(guān)系;每個結(jié)點由數(shù)據(jù)域和指針域組成指針域:存放下一個結(jié)點元素的地址每個結(jié)點元素沒有自己的名字,只能由指針維系結(jié)點元素之間的接序關(guān)系;一旦某個元素的指針“斷開”,后續(xù)元素就再也無法找尋。8.6結(jié)構(gòu)的自引用頭指針:指向鏈表的開始;頭結(jié)點:該結(jié)點的數(shù)據(jù)域中不存放數(shù)據(jù);尾結(jié)點:鏈表最后一個結(jié)點的指針域置成‘\0’,標(biāo)志鏈表的結(jié)束;每個結(jié)點的指針域存放下一結(jié)點的地址;單向鏈表:只能從當(dāng)前結(jié)點找到后繼結(jié)點。鏈表的建立、結(jié)點數(shù)據(jù)域的輸出、結(jié)點的插入和刪除。8.6結(jié)構(gòu)的自引用頭結(jié)點87頭指針\09建立帶有頭結(jié)點的單向鏈表讀取數(shù)據(jù)生成新結(jié)點將數(shù)據(jù)存入結(jié)點的成員變量中將新結(jié)點插入到鏈表中8.6結(jié)構(gòu)的自引用頭結(jié)點87頭指針\09struct
*create_slist1(){intc;
structslist
*h,*s,*r;
h=(structslist)malloc(sizeof(structslist));
r=h;
scanf(“%d”,&c);while(c!=-1){s=(structslist)malloc(sizeof(structslist));
s->data=c;r->next=s;r=s;
scanf(“%d”,&c);}
r->next=‘\0’;returnh;}main(){
structslist
*head;······
head=create_slist1();······}8.6結(jié)構(gòu)的自引用structslist{intdata;
structslist
*next;}順序訪問鏈表中各結(jié)點的數(shù)據(jù)域工作指針p:從頭到尾依次指向鏈表中的每個結(jié)點當(dāng)指針指向某個結(jié)點時,就輸出該結(jié)點數(shù)據(jù)域中的內(nèi)容;直到遇到鏈表結(jié)束標(biāo)志為止;如果是空鏈表,只輸出有關(guān)信息并返回調(diào)用函數(shù)。8.6結(jié)構(gòu)的自引用voidprint_slist(structslist
*head){
structslist
*p;
p=head->next;if(p==‘\0’)printf(“Linklistisnull!\n”);else{printf(“head”);do{printf(“->%d”,p->data);
p=p->next;}while(p!=‘\0’);
printf(“->end\n”);}}8.6結(jié)構(gòu)的自引用structslist{intdata;
structslist
*next;}頭結(jié)點87頭指針\09在單向鏈表中插入結(jié)點確定插入的位置后插:當(dāng)插入結(jié)點插在指針p所指的結(jié)點之后;前插:當(dāng)插入結(jié)點插在指針p所指的結(jié)點之前,當(dāng)進行前插操作時,需要三個工作指針;s:指向新開辟的結(jié)點;p:指向插入的位置;q:指向p的前趨結(jié)點。8.6結(jié)構(gòu)的自引用s879pq例:編寫函數(shù)insert_snode,在值為x的結(jié)點前插入值為y的結(jié)點,若值為x的結(jié)點不存在,則插在表尾。在進行插入的過程中,可能遇到三種情況:鏈表非空,值為x的結(jié)點存在,新結(jié)點應(yīng)插在該結(jié)點之前;鏈表非空,但值為x
的結(jié)點不存在,按要求,新結(jié)點應(yīng)插在鏈表的結(jié)尾;鏈表為空表,這種情況相當(dāng)于值為x
的結(jié)點不存在,新結(jié)點應(yīng)插在鏈表的結(jié)尾,即插在頭結(jié)點之后,作為鏈表的第一個結(jié)點;8.6結(jié)構(gòu)的自引用insert_snode(structslist*head,intx,inty){structslist*s,*p,*q;s=(structslist*)malloc(sizeof(structslist));s->data=y;q=head;p=head->next;while((p!=‘\0’)&&(p->data!=x)){q=p;p=p->next;}s->next=p;q->next=s;}8.6結(jié)構(gòu)的自引用structslist{intdata;
structslist
*next;}刪除單向鏈表中的結(jié)點找到待刪除結(jié)點的前趨結(jié)點q;將此前趨結(jié)點的指針域指向待刪除結(jié)點的后續(xù)結(jié)點;釋放被刪結(jié)點所占存儲空間。8.6結(jié)構(gòu)的自引用頭指針h頭結(jié)點78p9q8.6結(jié)構(gòu)的自引用二叉樹的數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)。二叉樹中每個結(jié)點記錄一個不同的單詞,結(jié)點內(nèi)容如下:指向該單詞內(nèi)容的指針該單詞出現(xiàn)的次數(shù)指向左孩子結(jié)點的指針指向右孩子結(jié)點的指針定義結(jié)點的結(jié)構(gòu):
structtnode
{char*word;
intcount;
struct
tnode
*left;
struct
tnode
*right;};這就是結(jié)構(gòu)的自引用。left和right是指向結(jié)構(gòu)的指針,而不是一個結(jié)點。*left*right*wordcounttnode8.6結(jié)構(gòu)的自引用若輸入如下單詞:C++、Java、Fortran、basic、Foxbase、C++,二叉樹的生成過程如下:*left*rightC++count*left*rightBasiccount*left*rightFoxbasecountCount=2*left*rightJavacount*left*rightFortrancount8.6結(jié)構(gòu)的自引用#defineMAXWORD20main(){
struct
tnode
*root,*tree();
char*t;
root=NULL;while((t=getword())!=NULL)
root=tree(root,t);
treeprint(root);}char*getword(){char*p;if((p=malloc(MAXWORD+1))==NULL)
{printf(“Outofmemory\n”);return(NULL);}
scanf(“%MAXWORDs”,p);
if(strlen(p)==0)return(NULL);
return(p);}8.6結(jié)構(gòu)的自引用struct
tnode
*tree(p,w)structtnode
*p;char*w;{struct
tnode
*talloc();
intcond;if(p==NULL){p=talloc();p->word=w;p->count=1;p->left=p->right=NULL;}elseif((cond=strcmp(w,p->word))==0)p->count++;elseif(cond<0)p->left=tree(p->left,w);else8.6結(jié)構(gòu)的自引用
p->right=tree(p->right,w);return(p);}treeprint(p)struct
tnode
*p;{if(p!=NULL){treeprint(p->left);
printf(“%4d%s\n”,p->count,p->word);
treeprint(p->right);}}struct
tnode
*talloc(){return((struct
tnode*)malloc(sizeof(struct
tnode)));}8.6結(jié)構(gòu)的自引用8.7位域—存儲空間的充分利用為了節(jié)省存儲空間,往往需要把幾個對象擠進一個機器字去。例如:
struct
packed-data{unsigneda:2;
unsignedb:6;
unsignedc:4;unsignedd:4;
inti;}data;struct
packed-data{unsigneda:2;
unsignedb:3;
unsignedc:4;inti;}data;1.若某一位域要從另一個字開始存放,可以用以下形式定義:unsigneda:1;unsignedb:2;
一個儲存單元unsigned:0;unsignedc:3;(另一個單元)本來a,b,c應(yīng)連續(xù)存放在一個存儲單元(字)中,由于使用了長度為0的位域,其作用是使下一個位域從下一個存儲單元開始存放。因此a,b存儲在一個存儲單元中,而將c存放在另一個存儲單元中。8.7位域—存儲空間的充分利用2.一個位域必須存儲在同一存儲單元中,不能跨兩個單元。如果第一個存儲單元所??臻g不能容納下一個位域,則該空間不用,而從下一個單元起存放該位域。3.可以定義無名位域。如:unsigneda:1;unsigned:2;(兩個空間不用)unsignedb:3;unsignedc:4;4.位域的長度不能大于存儲單元的長度,也不能定義位域數(shù)組。8.7位域—存儲空間的充分利用5.位域可以用整型格式輸出。如:printf(“%d,%d,%d”,data.a,data.b,data.c);6.位域可以在數(shù)值表達式中引用,它會被系統(tǒng)自動地轉(zhuǎn)換成整型數(shù)。如:data.a+5/data.b8.7位域—存儲空間的充分利用8.8聯(lián)合(共用體)聯(lián)合:可以讓幾種不同類型的變量存放到同一段內(nèi)存單元中。是一種類似于結(jié)構(gòu)的復(fù)合類型。任一時刻只能有一個變量起作用。聯(lián)合類型變量的定義形式是:union
聯(lián)合類型名{成員列表}變量名列表;這里變量a,b,c的存儲空間:uniondata{inti;
charch;
floatf;}a,b,c;uniondata{inti;charch;floatf;};union
dataa,b,c;8.8聯(lián)合0f03a.ch0f030f02a.i0f030f020f010f00a.f當(dāng)編譯程序看到關(guān)鍵字union時,就會為聯(lián)合中最長的成員項保留一個足夠大的空間。聯(lián)合通常用于保存函數(shù)調(diào)用的返回值,以便于為程序的其它部分按不同的數(shù)據(jù)類型引用值。聯(lián)合變量的引用方式先定義了聯(lián)合變量才能引用它,而且不能引用聯(lián)合變量,只能引用聯(lián)合變量中的成員。8.8聯(lián)合union
u-tag{intival;floatfval;char*pval;}uval;成員引用時可用uval.ival、uval.fval聯(lián)合可以出現(xiàn)在結(jié)構(gòu)和數(shù)組中,反之亦然8.8聯(lián)合例如:struct{char*name;
intflags;
intutype;
union{intival;floatfval;char*pval;}uval;}symtab[NSYM];
*symtab[i].uval.pval8.8聯(lián)合聯(lián)合的特點同一個內(nèi)存段可用來存放幾種不同類型的成員,但在每一瞬間只能存放其中一種,即每個瞬間只有一個成員起作用,其它成員不起作用。聯(lián)合中起作用的是最后一次存放的成員。聯(lián)合變量的地址和它的各成員的地址相同。不能在定義聯(lián)合變量的同時對其進行初始化。不能把聯(lián)合變量作為函數(shù)的參數(shù),也不能使函數(shù)帶回聯(lián)合變量,但可以使用指向聯(lián)合變量的指針。使用聯(lián)合比使用結(jié)構(gòu)更能節(jié)省存儲空間,但其代價是訪問成員的速度要慢一些。8.8聯(lián)合例:利用共同體的特點分別取出int變量中高字節(jié)和低字節(jié)中的兩個數(shù)。unionchange{charc[2];
inta;}un;main(){un.a=16961;
printf(“%d,%c\n”,un.c[0],un.c[0]);
printf(“%d,%c\n”,un.c[1],un.c[1]);}8.8聯(lián)合un.c[1]un.c[0]01000010010000100f010f02un.a66,B65,A例8.4從鍵盤上讀10個值,每個值從一新行開始讀起,以字符I或C開頭,指出此值是整數(shù)還是字符。把這些值保存在鏈表中,重新顯示。#include“stdio.h”#defineINTEGER‘I’#defineCHARACTER‘C’#defineERROR{printf(“Error\n”);return;}#defineSKIPwhile(getchar()!=‘\n’);8.8聯(lián)合main(){inti;
structitem{union{charc;
inti;}val;
intwhat;
structitem*next;}*p,*temp;if((p=(structitem*)malloc(sizeof(structitem))==NULL)ERRORtemp=p;for(i=0;;i++){switch(getchar()){caseINTEGER:p->what=0;
scanf(“%d”,&(p->vali));break;caseCHARACTER:p->what=1;
scanf(“%c”,&(p->valc));break;default:ERROR}SKIPif(i==9)break;else{if((p->next=(structitem*)malloc(sizeof(structitem)))==NULL)ERRORp=p->next;}}for(i=0,p=temp;i<10;p=p->next,i++)if(p->what)
printf(“%c”,p->valc);elseprintf(“%d”,p->vali);}8.9枚舉類型枚舉類型是ANSIC新標(biāo)準(zhǔn)所增加的。枚舉:將變量的可能取值一一列舉出來,變量的值只限于列舉出來的值的范圍。定義枚舉類型用關(guān)鍵字enum開頭。例如:enum
weekday{sun,mon,tue,wed,thu,fri,sat};enum
weekdayworkday,week-end;weekday和week-end被定義為枚舉類型變量,它們的值只能是sun到sat之一。例如:workday=mon;
或week-end=sun;在C語言編譯中,將枚舉元素按常量處理。它們不是變量,不能對它們賦值。枚舉元素作為常量,它們是有值的。C語言編譯時按定義的順序使它們的值為0,1,2,…,n在上面定義中,sun的值是0,mon的值為1,sat為6。
workday=mon;
printf(“%d”,workday);將輸出整數(shù)1。8.9枚舉類型也可以在定義時由程序員指定枚舉元素的值,如:
enum
weekday{sun=7,mon=1,tue,wed,thu,fri,sat};枚舉值可以進行比較運算。其比較規(guī)則是:按其在定義時的順序號比較。如果定義時沒有人為指定序號,則第一個枚舉元素值認(rèn)作0。一個整數(shù)不能直接賦給一個枚舉變量。但可以通過強制類型轉(zhuǎn)換賦值。如:workday=(enum
weekday)2;8.9枚舉類型8.10typedef定義類型C語言中可以用typedef來定義一個新的類型名。例如:
typedefintLENGTH;LENGTHlen,maxlen;LENGTH*lengths[];同樣,說明typedefchar*STRING;STRINGp,lineptr[LINES];也可以定義結(jié)構(gòu)類型:typedef
struct{
intmonth;
intday;
intyear;}DATE;用typedef來定義的類型名總是用大寫字母書寫的。一個更復(fù)雜的例子:為本章中的樹結(jié)點寫出類型定義:typedef
structtnode{char*word;
intcount;
structtnode*left;
structtnode*right;}TREENODE,*TREEPTR;#define是在預(yù)編譯時處理的,它只能做簡單的字符串替換,而typedef是在編譯時處理的。實際上它并不是做簡單的字符串替換。8.10typedef定義類型使用typedef有兩個主要的理由:有利于程序移植。如果把typedef用于可能與機器有關(guān)的數(shù)據(jù)類型,則在程序移植時僅需改變typedef,從而減少大量的程序修改工作。使用typedef能為程序提供更多的可讀信息,用一個適當(dāng)?shù)姆柮硎疽粋€復(fù)雜的結(jié)構(gòu)類型會增強程序的可讀性。8.10typedef定義類型寫一個函數(shù)建立一個有5名學(xué)生數(shù)據(jù)的單向鏈表structstudent{longnum;floatscore;
structstudent
*next;};#defineLENsizeof(st
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 化膿性腹膜炎病人的護理《外科護理學(xué)》
- 二零二五年家具展會參展及廣告投放合同3篇
- 二零二五年度快艇改裝設(shè)計與性能優(yōu)化協(xié)議3篇
- 二零二五年度新型零售店長管理合作協(xié)議3篇
- 二零二五年度地下綜合管廊工程聯(lián)合經(jīng)營協(xié)議書模板3篇
- 小英雄雨來完美版課件
- 二零二五年度全國性品牌代理包銷合同范本2篇
- 二零二五年度建筑材料運輸配送合同3篇
- 二零二五年度房地產(chǎn)廣告合作分成合同2篇
- 2025年度電子政務(wù)平臺軟件升級與全面售后服務(wù)協(xié)議范本3篇
- 機動車維修竣工出廠合格證
- 陜西延長石油精原煤化工有限公司 60 萬噸 - 年蘭炭綜合利用項目 ( 一期 30 萬噸 - 年蘭炭、1 萬噸 - 年金屬鎂生產(chǎn)線)竣工環(huán)境保護驗收調(diào)查報告
- 大病救助申請書
- 法學(xué)概論-課件
- 廈門物業(yè)管理若干規(guī)定
- 外科護理學(xué)試題+答案
- 齊魯醫(yī)學(xué)屈光和屈光不正匯編
- 貨架的技術(shù)說明(一)
- 【高等數(shù)學(xué)練習(xí)題】皖西學(xué)院專升本自考真題匯總(附答案解析)
- 高處作業(yè)安全技術(shù)交底-
- 工抵房協(xié)議模板
評論
0/150
提交評論