




已閱讀5頁,還剩15頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第九章 結(jié)構(gòu)和聯(lián)合日常生活中要處理的數(shù)據(jù)往往不是由單一類型的數(shù)據(jù)構(gòu)成。例如,一個(gè)學(xué)生的基本信息就是由姓名、學(xué)號、性別、出生日期、所在院系、專業(yè)、班級等基本“數(shù)據(jù)項(xiàng)”共同構(gòu)成。每個(gè)基本數(shù)據(jù)項(xiàng)都具有自己的屬性(名稱、數(shù)據(jù)類型、長度等)。人們常常需要對由若干不同屬性的數(shù)據(jù)項(xiàng)所組成的整體數(shù)據(jù)進(jìn)行組織和處理。但由于各數(shù)據(jù)項(xiàng)的屬性不盡相同,所以用數(shù)組亦不能有效地對其進(jìn)行組織和處理。為此,語言提供了與數(shù)組類型不同的另一種構(gòu)造類型 結(jié)構(gòu)類型。9.1 結(jié)構(gòu)類型和結(jié)構(gòu)變量和數(shù)組相似,結(jié)構(gòu)也是擁有若干分量的一種構(gòu)造類型。但和數(shù)組不同的是,結(jié)構(gòu)的各個(gè)分量可以分別具有不同的數(shù)據(jù)類型。結(jié)構(gòu)的每一個(gè)分量都稱為是該結(jié)構(gòu)的一個(gè)“成員”。結(jié)構(gòu)成員的數(shù)據(jù)類型可以是基本數(shù)據(jù)類型,也可以是指針、數(shù)組或其他結(jié)構(gòu)類型。結(jié)構(gòu)類型的定義形式是:struct 結(jié)構(gòu)類型名類型1 成員1;類型2 成員2;類型n 成員n;例如:struct dateint year;unsigned short month;unsigned short day;在這個(gè)定義中,定義了一個(gè)新的數(shù)據(jù)類型date ,這是一個(gè)結(jié)構(gòu)類型,共有三個(gè)成員,分別是year、month和day。每個(gè)成員都有自己的數(shù)據(jù)類型,比如month的數(shù)據(jù)類型是無符號短整型。定義了結(jié)構(gòu)類型之后,我們便可以用其來定義相應(yīng)的結(jié)構(gòu)變量。可以采用以下三種方法來定義結(jié)構(gòu)變量。1先定義結(jié)構(gòu)類型再定義結(jié)構(gòu)變量首先定義一個(gè)結(jié)構(gòu)類型(如上面的date),然后再用其來定義結(jié)構(gòu)變量。定義形式為:struct 結(jié)構(gòu)類型名 變量1,變量2,變量n;例如:struct date d1,d2;便定義了兩個(gè)date型的結(jié)構(gòu)變量d1和d2。同前面介紹的變量一樣,每個(gè)結(jié)構(gòu)變量所需的存儲空間大小也是由其類型決定的。如上面d1和d2所需的存儲空間大小為sizeof(struct date)個(gè)字節(jié)。注意,在用這種方法定義結(jié)構(gòu)變量時(shí),“struct”和“結(jié)構(gòu)類型名”部分均不能省略。通常我們將程序中所用到的所有結(jié)構(gòu)類型都在程序的頭部或某一個(gè)頭文件中集中定義。然后再根據(jù)需要用上述方法定義相應(yīng)的結(jié)構(gòu)變量。注意,定義結(jié)構(gòu)類型時(shí)并不產(chǎn)生存儲分配,只有在定義結(jié)構(gòu)變量時(shí)才涉及到存儲分配。2在定義結(jié)構(gòu)類型的同時(shí)定義結(jié)構(gòu)變量我們可以在定義結(jié)構(gòu)類型的同時(shí)再定義相應(yīng)的結(jié)構(gòu)變量。例如:struct studentlong num;char name21;char sex;unsigned short age;unsigned class_num;char come_from31;float average_score; student1,student2;它的作用是定義了一個(gè)結(jié)構(gòu)類型student,然后緊接著又定義了兩個(gè)該類型的結(jié)構(gòu)變量student1和student2。3直接定義結(jié)構(gòu)變量此種方法和上面第二種方法類似,只不過沒有定義結(jié)構(gòu)類型名。其形式為:struct 類型1 成員1;類型2 成員2;類型n 成員n; 變量1,變量2,變量n;例如:structchar name21;unsigned short age;char sex; p1,p2,p3;定義了三個(gè)結(jié)構(gòu)變量p1,p2,p3。但由于沒有定義相應(yīng)的結(jié)構(gòu)類型,所以如果以后想再定義一個(gè)同類型的結(jié)構(gòu)變量p4的話,上述語句還要重寫一遍。再者,當(dāng)結(jié)構(gòu)的類型發(fā)生變化時(shí),結(jié)構(gòu)變量的定義也需重寫。因此我們不提倡用這種辦法來定義結(jié)構(gòu)變量,除非編程者清楚地知道以后不會再用到該結(jié)構(gòu)類型。上面我們介紹了結(jié)構(gòu)類型及結(jié)構(gòu)變量的定義方法。此外,一個(gè)結(jié)構(gòu)的成員也可以是另一個(gè)結(jié)構(gòu)。例如:struct dateint year;unsigned short month;unsigned short day;struct personchar name21;char sex;struct date birthday; /* 結(jié)構(gòu)person的成員birthday又是另一個(gè)結(jié)構(gòu)date */char department81;9.2 訪問結(jié)構(gòu)成員在定義了一個(gè)結(jié)構(gòu)變量之后,便可以訪問這個(gè)變量的成員。引用方式為:結(jié)構(gòu)變量名.成員名這里,“.”稱為“成員運(yùn)算符”。例如:struct date d1,d2;d1.year=2002;d1.month=12;d1.day=25;d2.year=d1.year;d2.month=d1.month;d2.day=d1.day;printf(d1.year=%d, d1.month=%d, d1.day=%dn, d1.year, d1.month,d1.day);printf(d2.year=%d, d2.month=%d, d2.day=%dn, d2.year, d2.month,d2.day);從附錄可知,成員運(yùn)算符“”在所有的運(yùn)算符中優(yōu)先級最高,因此可以把上面的d1.year和d1.month 等當(dāng)作為一個(gè)整體來看待。如:d1.year+; 等價(jià)于 (d1.year)+;d1.mongth+=2; 等價(jià)于 (d1.mongth)+=2;d2.day=d1.day+; 等價(jià)于 d2.day=(d1.day)+;需要注意的是:l 舊的標(biāo)準(zhǔn)規(guī)定不能將一個(gè)結(jié)構(gòu)變量作為一個(gè)整體直接賦給另一個(gè)具有相同結(jié)構(gòu)類型的結(jié)構(gòu)變量,而只能對各個(gè)成員分別賦值。如:d2.year=d1.year;d2.month=d1.month;d2.day=d1.day;l 新的標(biāo)準(zhǔn)允許將一個(gè)結(jié)構(gòu)變量直接賦給另一個(gè)具有相同結(jié)構(gòu)類型的結(jié)構(gòu)變量。如:d2=d1;l 如果結(jié)構(gòu)變量的成員本身是一個(gè)結(jié)構(gòu)類型,則要用若干個(gè)成員運(yùn)算符,一級一級地找到最低層的成員。且只能對最低層的成員進(jìn)行賦值、存取或運(yùn)算。例如:struct person myself;strcpy(,ZhaoYongZhe);myself.sex=M;myself.birthday.year=1961;myself.birthday.month=4;myself.birthday.day=17;strcpy(myself.department,Computer College of Jilin University);注意:成員運(yùn)算符“”是自左向右結(jié)合的。所以myself.birthday.year=1961; 等價(jià)于 (myself.birthday).year=1961;l 和數(shù)組一樣,標(biāo)準(zhǔn)規(guī)定,只有當(dāng)結(jié)構(gòu)變量為全局變量或靜態(tài)變量時(shí),才能在定義時(shí)對其初始化(但有些編譯系統(tǒng)已取消了此限制)。例如:static struct person myself=ZhaoYongZhe,M,1961,4,17,Computer College of Jilin University;9.3 結(jié)構(gòu)數(shù)組和結(jié)構(gòu)指針9.3.1 結(jié)構(gòu)數(shù)組當(dāng)數(shù)組中的每個(gè)元素都是同一類型的結(jié)構(gòu)變量時(shí),該數(shù)組稱為結(jié)構(gòu)數(shù)組。例如:struct studentlong num;char name21;char sex;unsigned short age;unsigned class_num;char come_from31;float average_score;/* 下面定義了一個(gè)一維student型結(jié)構(gòu)數(shù)組stu并對其初始化 */static struct student stu3=200101,LiuMing,M,19,1,Shanghai,78.45,200102,WangMei,F,18,2,Changchun,94.78,200101,Zhangkai,M,20,3,Beijing,54.45;9.3.2 結(jié)構(gòu)指針結(jié)構(gòu)對象的地址即為指向該結(jié)構(gòu)對象的指針。我們可以定義一個(gè)結(jié)構(gòu)指針變量來存放相應(yīng)結(jié)構(gòu)對象的地址。例如:struct student stu_1,stu_2,*p_stu;p_stu=&stu_1;9.3.3 通過指向結(jié)構(gòu)的指針訪問結(jié)構(gòu)成員我們可用前面介紹的成員運(yùn)算符“.”來訪問結(jié)構(gòu)的成員。例如:struct student stu_1,stu_2,*p_stu=&stu_1;則stu_1.age=21;等價(jià)于(*p_stu).age=21;注意(*p_stu).age不能寫成 *p_stu.age,這是因?yàn)槌蓡T運(yùn)算符“.”的優(yōu)先級高于指針運(yùn)算符“*”的優(yōu)先級。所以*p_stu.age等同于*(p_stu.age)而不是(*p_stu).age。由于經(jīng)常要通過指向結(jié)構(gòu)的指針來訪問結(jié)構(gòu)的成員。所以語言專門提供了一個(gè)指針成員運(yùn)算符“-”。它是由一個(gè)減號“-”和一個(gè)大于號“”共同組成。其用法為:結(jié)構(gòu)指針-成員名且有:“結(jié)構(gòu)指針-成員名”等價(jià)于“(*結(jié)構(gòu)指針).成員名”。所以上面的(*p_stu).age=21;也可以寫成p_stu-age=21;注意“.”和“-”的優(yōu)先級相同,均是自左向右結(jié)合的。至于采用哪一個(gè)則要看是通過結(jié)構(gòu)變量還是結(jié)構(gòu)指針來訪問結(jié)構(gòu)的成員。對于結(jié)構(gòu)變量,只能通過“.”來訪問其成員。而對于結(jié)構(gòu)指針,盡管可以通過“*”和“.”來訪問其所指結(jié)構(gòu)對象的成員。但我們通常采用“-”的形式。還有一點(diǎn)要注意的是,結(jié)構(gòu)指針的增量操作也和其他指針的增量操作一樣,是以其所指對象所需占用的字節(jié)數(shù)為“單位”進(jìn)行的??聪旅娴睦樱豪?.1 讀入10個(gè)學(xué)生的信息,然后將平均成績最高和最低者的姓名、班級、成績輸出。#include stdio.h#define N 10struct student /* 定義結(jié)構(gòu)類型student */long num;char name21;char sex;unsigned short age;unsigned class_num;char come_from31;float average_score;void main() struct student sN,*p,*p1,*p2;int i;for(i=0;iN;i+) /* 分別讀入每個(gè)學(xué)生的信息 */printf(Input the information of Student_%d:n,i+1);printf(Num=);scanf(%d,&si.num);printf(Name=);scanf(%s,);printf(Sex=);scanf(%c,&si.sex);printf(Age=);scanf(%d,&si.age);printf(Class_num=);scanf(%d,&si.class_num);printf(Come_from=);scanf(%s,e_from);printf(Average_Score=);scanf(%f,&si.average_score); for(p=p1=p2=s;+paverage_score p1-average_score) p1=p;if(p-average_score average_score) p2=p; printf(Name Class Average_Scoren);printf(-n);printf(%-20s%5u %fn,p1-name,p1-class_num,p1-average_score);printf(%-20s%5u %fn,p2-name,p2-class_num,p2-average_score);9.4 sizeof運(yùn)算符和的動態(tài)存儲分配函數(shù)在語言中,sizeof是“求字節(jié)數(shù)”運(yùn)算符,其優(yōu)先級與+、-等運(yùn)算符相同。sizeof的運(yùn)算對象是數(shù)據(jù)類型,其返回值是這種類型數(shù)據(jù)在內(nèi)存中占用的字節(jié)數(shù)。例如:sizeof(int),sizeof(double *),sizeof(struct student)等等。盡管同一種數(shù)據(jù)類型的對象(如int型)在不同的編譯系統(tǒng)中可能被分配了不同字節(jié)數(shù)的存儲空間,但sizeof總能返回正確的字節(jié)數(shù)。所以建議大家使用sizeof來取代相應(yīng)的整常數(shù)。這樣編出的程序可實(shí)現(xiàn)與編譯系統(tǒng)的無關(guān)性。此外,語言也是一個(gè)與操作系統(tǒng)(OS - Operation System)無關(guān)型的程序設(shè)計(jì)語言。因?yàn)樗行枧c操作系統(tǒng)打交道的工作皆由相應(yīng)的庫函數(shù)來完成。所以用語言編程離開庫函數(shù)將寸步難行。我們知道在程序中使用得最多的便是“自動變量”。而對自動變量的存儲分配并不是在編譯時(shí)完成,而是在程序運(yùn)行時(shí)根據(jù)需要動態(tài)地進(jìn)行。為了動態(tài)地分配存儲空間,標(biāo)準(zhǔn)特提供了一個(gè)名為malloc的庫函數(shù),其定義形式如下:void *malloc(bytes)unsigned bytes;malloc函數(shù)向操作系統(tǒng)申請一塊長度為bytes個(gè)字節(jié)的連續(xù)存儲空間,如申請成功,則返回一個(gè)無類型指針(void型指針),其指向所分配空間的第一個(gè)字節(jié)。如果操作系統(tǒng)沒有足夠的可用空間,則malloc返回一個(gè)空指針NULL用以表明空間分配失敗。注意,無類型指針相當(dāng)于是一個(gè)“地址類型”或“指針類型”。由于其無類型或類型不定,所以必須對其進(jìn)行強(qiáng)制類型轉(zhuǎn)換后才能使用。從這個(gè)意義上說,void型指針又可看成是一個(gè)“萬能指針”,可以根據(jù)需要將其轉(zhuǎn)換為任意類型的指針,反之亦然。而NULL實(shí)際上是一個(gè)宏,它是在頭文件stdio.h定義的。malloc函數(shù)的用法如下:char *p;p=(char*)malloc(10); /* 申請10個(gè)字節(jié)的空間,并將其首地址轉(zhuǎn)換為字符指針 */if(p=NULL)puts(memory allocation failed.);elseputs(memory allocation successful.);相對于庫函數(shù)malloc,語言還提供了另一個(gè)庫函數(shù)free,函數(shù)free的定義形式如下:void free(p)void *p;與malloc正好相反,函數(shù)free將p所指向的存儲空間歸還(釋放)給操作系統(tǒng)。作為一個(gè)良好的程序設(shè)計(jì)習(xí)慣,在動態(tài)申請的空間使用完畢之后,應(yīng)立即將其釋放。注意,在用free(p)將p所指的空間釋放之后,p的值不變,即其仍指向原來的存儲空間。顯然,不訪問這個(gè)已被釋放的存儲空間是程序員的職責(zé)??聪旅胬樱豪?.2 從鍵盤讀入一個(gè)正整數(shù)n,然后再依次讀入n個(gè)整數(shù),并按讀入的反序?qū)⑺麄冚敵觥?include void main() int *p,i,n;printf(Input the number of the integers: );scanf(%d,&n);while(n=0)printf(Invalid number! Input it again: );scanf(%d,&n);if( (p=(int*)malloc(n*sizeof(int) = NULL ) /* 申請一個(gè)動態(tài)一維數(shù)組p */puts(Memory allocation failed ! );getchar();exit(0);printf(Input %d integers:n,n);for(i=0;inum);printf(Name=%sn,s-name);printf(Sex=%cn,s-sex);printf(Age=%dn,s-age);printf(Class_num=%dn,s-class_num);printf(Come_from=%sn,s-come_from);printf(Average_Score=%fn,s-average_score);9.6 結(jié)構(gòu)的自引用前面我們提到,在定義結(jié)構(gòu)類型時(shí),一個(gè)結(jié)構(gòu)的成員也可以是另一個(gè)結(jié)構(gòu)類型。例如:struct personchar name21;char sex;struct date birthday; /* person的成員birthday又是另一個(gè)結(jié)構(gòu)date */char department81;但下面的定義卻是非法的:struct personchar name21;char sex;char department81;struct person father; /* person的成員father 又是結(jié)構(gòu)person */;因?yàn)樯厦嬖诙x結(jié)構(gòu)person時(shí)產(chǎn)生無窮遞歸,所以無法對其進(jìn)行存儲空間分配。換句話說,一個(gè)person類型的對象將需要無限的存儲空間。所以上述的定義是非法的。但下面的定義卻是合法的:struct personchar name21;char sex;char department81;struct person *father; /* person的成員father 是一個(gè)person結(jié)構(gòu)指針 */;這就是結(jié)構(gòu)的自引用。注意,上面的定義不會產(chǎn)生無窮遞歸,因?yàn)榻Y(jié)構(gòu)person的成員father 只是一個(gè)指向person結(jié)構(gòu)的指針,而不是person結(jié)構(gòu)。所以一個(gè)person類型的對象僅需要有限的存儲空間。結(jié)構(gòu)的自引用通常用于構(gòu)造“鏈表”,它是數(shù)據(jù)結(jié)構(gòu)課程中的重點(diǎn)內(nèi)容。在本書中不作介紹。9.7 位域存儲空間的充分利用對于前面介紹的所有結(jié)構(gòu),他們成員的最小存儲單位均為“字節(jié)”。即結(jié)構(gòu)的每個(gè)成員至少要占用一個(gè)字節(jié)的存儲空間。如上面結(jié)構(gòu)person的成員sex(性別),盡管只需1位的空間便足夠了,但其卻占用了一個(gè)字節(jié)。為了節(jié)省存儲空間,語言允許用若干二進(jìn)制位來存放結(jié)構(gòu)的成員,這就是“位域”。所謂位域即是以二進(jìn)制位為存儲單位的結(jié)構(gòu)成員。例如:struct personchar name21;unsigned sex:1;unsigned age:7;定義了一個(gè)結(jié)構(gòu)類型person,其共有三個(gè)成員,其中成員sex和age都是位域。sex占1位存儲空間,age占7位存儲空間。但成員name不是位域。位域的引用與非位域一樣,例如:例9.3#include #include struct person char name21; unsigned sex:1; unsigned age:7;main() struct person p,*pp=&p; strcpy(, Zhang Wei); p.sex=1; pp-age=27; printf(=%s,p.sex=%u,p.age=%un,,p.sex,p.age); printf(sizeof(struct person)=%dn,sizeof(struct person);結(jié)果為:= Zhang Wei,p.sex=1,p.age=27sizeof(struct person)=22關(guān)于位域的定義和引用,要注意以下幾點(diǎn):l 位域的長度不能超過一個(gè)存儲單元的長度。存儲單元的長度由具體的編譯系統(tǒng)決定,通常是一個(gè)“字”的長度。如Turbo C 3.0 是16位。l 若某一位域要從另一個(gè)儲存單元開始存放,可以用以下形式定義:unsigned a:1;unsigned b:2; /* a,b存于同一個(gè)儲存單元 */:0;unsigned c:3; /* c存于另一個(gè)存儲單元 */本來a,b,c應(yīng)連續(xù)存放在一個(gè)存儲單元中,由于使用了長度為0的位域,其作用是使緊跟其后的下一個(gè)位域從下一個(gè)存儲單元開始存放。因此a,b存儲在同一個(gè)存儲單元中,而將c存放在另一個(gè)存儲單元中。l 可以定義無名位域,來跳過相應(yīng)的“位”。如:unsigned a:1;:2; /* 跳過兩位不用 */unsigned b:3;unsigned c:4;l 位域的類型通常為無符號整型。9.8 聯(lián)合9.8.1 聯(lián)合類型和聯(lián)合變量聯(lián)合也是一種類似于結(jié)構(gòu)的構(gòu)造類型。與結(jié)構(gòu)類似,聯(lián)合類型的定義形式是:union 聯(lián)合類型名類型1 成員1;類型2 成員2;類型n 成員n;例如:union dataint i;char ch;float f;定義了一個(gè)新的數(shù)據(jù)類型data ,這是一個(gè)聯(lián)合類型,其共有三個(gè)成員,分別是i、ch和f。每個(gè)成員都有自己的數(shù)據(jù)類型,比如f的數(shù)據(jù)類型是float型。定義了聯(lián)合類型之后,我們便可以用其來定義相應(yīng)的聯(lián)合變量。同結(jié)構(gòu)變量的定義一樣,我們也可以采用以下三種方法來定義聯(lián)合變量。1先定義聯(lián)合類型再定義聯(lián)合變量首先定義一個(gè)聯(lián)合類型(如上面的data),然后再用其來定義聯(lián)合變量。定義形式為:union 聯(lián)合類型名 變量1,變量2,變量n;例如:union data u1,u2;便定義了兩個(gè)data型的聯(lián)合變量u1和u2。2在定義聯(lián)合類型的同時(shí)定義聯(lián)合變量我們可以在定義聯(lián)合類型的同時(shí)再定義相應(yīng)的聯(lián)合變量。例如:union dataint i;char ch;float f; u1,u2;它的作用是定義了一個(gè)聯(lián)合類型data,然后緊接著又定義了兩個(gè)該類型的聯(lián)合變量u1和u2。3直接定義聯(lián)合變量此種方法和上面第二種方法類似,只不過沒有定義聯(lián)合類型名。其形式為:union類型1 成員1;類型2 成員2;類型n 成員n; 變量1,變量2,變量n;例如:unionint i;char ch;float f; u1,u2;結(jié)構(gòu)和聯(lián)合的區(qū)別是,結(jié)構(gòu)的各個(gè)成員分別具有各自的存儲空間,而聯(lián)合的各個(gè)成員則共享同一塊存儲空間。所以結(jié)構(gòu)變量所占據(jù)存儲空間的大小是其各個(gè)成員所需存儲空間之和,而聯(lián)合變量所占據(jù)存儲空間的大小是其各個(gè)成員所需存儲空間的最大者。利用聯(lián)合,可以將幾種不同類型的變量存放到同一塊內(nèi)存單元中。例如,上面的聯(lián)合類型data便將一個(gè)int型變量i、一個(gè)char型變量ch、一個(gè)float型變量f放在從同一個(gè)地址開始的內(nèi)存單元中:ichf9.8.2 聯(lián)合變量的引用方式聯(lián)合變量的引用方式與結(jié)構(gòu)變量相同,我們也可以通過“.”和“-”來飲用其成員。例如:union data u,*p=&u;u.i=123;p-ch=A;但由于聯(lián)合變量的各個(gè)成員都共享同一塊存儲空間,所以在任一時(shí)刻只能有一個(gè)成員在起作用。也就是說,盡管一個(gè)聯(lián)合變量有多個(gè)成員,但只有一個(gè)成員的“值”是有意義的,而引用其他成員的“值”都是無意義的。這個(gè)成員便是最近一次賦值所引用的成員。例如:例9.4#include union dataint i;char ch;float f;main() union data u;u.i=123;u.ch=A;u.f=123.456;printf(u.i = %dn,u.i);printf(u.ch = %cn,u.ch);printf(u.f = %fn,u.f);結(jié)果為:u.i = -5767u.ch = yu.f = 123.456001可知對聯(lián)合變量u的成員f的引用是有意義的,而對成員i和ch的引用則是無意義的。這是因?yàn)閷β?lián)合變量u的最近一次賦值是對其成員f進(jìn)行的,它使得以前對其成員i和ch的賦值變得無效。這也是聯(lián)合與結(jié)構(gòu)的區(qū)別所在。9.8.3 聯(lián)合的特點(diǎn)聯(lián)合提供了一種能在同一塊存儲區(qū)域內(nèi)處理不同類型數(shù)據(jù)的方式。編譯會為聯(lián)合變量分配一塊存儲空間,該存儲空間的大小剛好能容納其最大的成員。這樣其所有成員便能共享該塊存儲空間。引入聯(lián)合的初衷是為了節(jié)省寶貴的內(nèi)存,讓多個(gè)變量“共享”同一塊內(nèi)存空間。這一點(diǎn)和FORTRAN語言中的EQUIVALENCE語句類似。但這樣一來也產(chǎn)生了一個(gè)負(fù)面作用,那就是不便于對變量進(jìn)行跟蹤,損失了程序的易讀性。這和現(xiàn)在所提倡的程序設(shè)計(jì)思想是相矛盾的。所以我們不提倡在程序中使用聯(lián)合。但有時(shí)聯(lián)合也是有其獨(dú)特作用的。例如,我們想知道在中int型數(shù)據(jù)是如何存放的,即高字節(jié)和低字節(jié)是如何組織的。為此編寫如下程序:例9.5#include union icint i;unsigned char ch2;main() union ic u;u.i=32767;printf(u.ch1=%X,u.ch0=%Xn,u.ch1,u.ch0);u.i=32768;printf(u.ch1=%X,u.ch0=%Xn,u.ch1,u.ch0);結(jié)果為:u.ch1=7F,u.ch0=FFu.ch1=80,u.ch0=0由此可知一個(gè)int型數(shù)據(jù)的低字節(jié)存放其低8位,而高字節(jié)存放其高8位。這正是利用了無符號字符數(shù)組ch與整形變量i共享同一塊存儲空間的特點(diǎn)。在使用聯(lián)合類型數(shù)據(jù)時(shí)要注意以下一些特點(diǎn):l 在任一時(shí)刻,聯(lián)合變量只有一個(gè)成員有意義,其它成員則無意義。正確地存取聯(lián)合變量的某個(gè)成員是程序設(shè)計(jì)者的職責(zé)。l 聯(lián)合變量中有意義的成員即是其最后一次賦值的成員。l 聯(lián)合變量的地址和其各成員的地址相同。l 不能在定義聯(lián)合變量的同時(shí)對其進(jìn)行初始化。9.9 枚舉類型枚舉類型是ANSI 新標(biāo)準(zhǔn)所增加的。如果一個(gè)變量只有幾種可能的值,則可以定義其為枚舉類型。所謂“枚舉”是指將變量的可能取值一一列舉出來,變量的值只限于列舉出來的值的范圍。定義枚舉類型用保留字enum。其定義形式為:enum 枚舉類型名 枚舉常量名=整形值, . 變量列表;例如:enum weekday sun,mon,tue,wed,thu,fri,sat;定義了一個(gè)枚舉類型weekday。該枚舉類型有7個(gè)枚舉常量,分別是sun、mon、tue、wed、thu、fri和sat。和結(jié)構(gòu)或聯(lián)合類型一樣,我們可以用枚舉類型來定義相應(yīng)的枚舉變量。如:enum weekday d1,d2; (enum不能省略)定義了兩個(gè)weekday型的枚舉變量d1和d2,它們的值可以是sun到sat之一。例如:d1=mon;d2=sun;我們也可以直接定義枚舉變量,例如:enum red,yellow,blue color1,color2;同樣,也可以同時(shí)定義枚舉類型及枚舉變量,例如:enum color red,yellow,blue color1,color2;枚舉類型實(shí)際上是一個(gè)int型常量的“集合”。亦即每一個(gè)枚舉常量實(shí)際上是一個(gè)int型常量,而枚舉變量實(shí)際上是一個(gè)int型變量。使用枚舉類型時(shí)要注意以下幾點(diǎn):1) 上述的枚舉常量sun,mon,red,blue等是int型常量,所以不能對它們賦值。2) 枚舉常量的值滿足:第i個(gè)枚舉常量的值 第i-1個(gè)枚舉常量的值 + 1 。3) 按的缺省規(guī)定,第一個(gè)枚舉常量的值為0。4) 在定義枚舉類型時(shí),可以指定每個(gè)枚舉常量的值。如不指定,則按第2條的規(guī)定決定其值。5) 使不同的枚舉常量具有不同的值是程序員的責(zé)任。6) 枚舉變量同int型變量,同樣,使其值落在合法的枚舉常量的范圍之內(nèi)也是程序員的責(zé)任。7) 對枚舉變量可進(jìn)行同int型變量一樣的運(yùn)算和操作。例9.6#include enum color red=3,green,blue=4;enum workday mon,tue,wed=7,thu,fri;main() enum color c1,c2;enum workday d1,d2;c1=red;c2=+c1;d1=mon;d2=wed;printf(c1=%d,c2=%dn,c1,c2);printf(d1=%d,d2=%dn,d1,d2);printf(red=%d,green=%d,blue=%dn,red,green,blue);printf(mon=%d,tue=%d,wed=%d,thu=%d,fri=%dn,mon,tue,wed,thu,fri);結(jié)果為:c1=4,c2=4d1=0,d2=7red=3,green=4,blue=4mon=0,tue=1,wed=7,thu=8,fri=9使用枚舉類型及枚舉變量的目的是增加程序的直觀性和易讀性。9.10 用typedef定義類型在語言中,還可以用typedef來定義一個(gè)新的“類型名”。例如:typedef int INTEGER;就定義了一個(gè)新的類型名“INTEGER”,即使INTEGER與int成為同義詞。此后 INTEGER 就能用在類型int能出現(xiàn)的任何地方,且作用完全相同。例如:INTEGER i1,i2; 等價(jià)于 int i1,i2;INTEGER a10,*p; 等價(jià)于 int a10,*p;同樣,typedef char *STRING;則定義了一個(gè)新類型名“STRING”,且其和類型(char *)成為同義詞,即STRING為字符指針類型。以后我們就可以用STRING來定義字符指針變量。例如:STRING p,linesMAX_LINES; 等價(jià)于 char *p,*linesMAX_LINES;注意,用typedef定義的新類型名并不是緊跟在保留字typedef之后,且具體的語法也不太容易用一個(gè)語法表達(dá)式來刻畫。我們可以這樣來描述typedef的用法:如果要定義一個(gè)新類型名,則首先定義一個(gè)與之同名的“同類型”的變量,然后再在該“變量的定義”前面加上保留字typedef,則該“變量”名便上升成為“類型”名。例如:struct int month;int day;int year; DATE;定義了一個(gè)“結(jié)構(gòu)變量”DATE,而typedef struct int month;int day;int year; DATE;則定義了一個(gè)相應(yīng)的“結(jié)構(gòu)類型”DATE。且DATE date1,date2;等價(jià)于typedef struct int month;int day;int year; date1,date2;可見,通過用typedef定義新類型可以簡化程序的書寫并提高程序的易讀性。而程序的“易讀性”是現(xiàn)代程序設(shè)計(jì)最重要的特性之一。他對程序的維護(hù)、功能擴(kuò)充、移植等都具有舉足輕重的作用。從前面的的預(yù)處理程序到現(xiàn)在的類型名定義,可以看出在這方面比別的程序設(shè)計(jì)語言有獨(dú)到的設(shè)計(jì),這也是之所以風(fēng)靡全球的原因之一。為了和的保留字以及變量名相區(qū)別,用typedef定義的類型名通??偸怯么髮懹⑽淖帜竵砻?。但必須強(qiáng)調(diào)的是,typedef并不是“創(chuàng)建”了一個(gè)新的數(shù)據(jù)類型,它只是為現(xiàn)有的某些數(shù)據(jù)類型起了一個(gè)新的名字而已,并沒有擴(kuò)展的數(shù)據(jù)類型。typedef與#define有相似之處。但事實(shí)上,它們二者是不同的。主要區(qū)別在:l typedef是的“保留字”,即不能用其來命名變量等對象,但define并不是的“保留字”,我們可以用其來命名變量,只不過不提倡這樣做而已。l #define是在預(yù)處理時(shí)處理的,它只能做簡單的字符串替換,而typedef是在編譯時(shí)處理的。實(shí)際上它并不是做簡單的字符串替換,例如:typedef int INTEGER; 在某些情況下可代之以 #define INTEGER int但 typedef int NUM10;卻無法以任何#define代之。使用typedef有兩個(gè)主要的理由:其一是有利于程序移植。如果把typedef用于可能與機(jī)器有關(guān)的數(shù)據(jù)類型,則在程序移植時(shí)僅需改變typedef,從而減少大量的程序修改工作。第二個(gè)原因是使用typedef能為程序提供更多的可讀信息,用一個(gè)適當(dāng)?shù)姆柮硎疽粋€(gè)復(fù)雜的結(jié)構(gòu)類型會增強(qiáng)程序的可讀性。習(xí) 題9.1 填空 語言提供了三種構(gòu)造數(shù)據(jù)類型,它們是 、 和 。 使幾個(gè)不同類型的量共享同一段內(nèi)存的結(jié)構(gòu),稱為“ ”。9.2 單項(xiàng)選擇 說明語句struct studentint num;char name20;char sex;定義了( )。(1) 結(jié)構(gòu)類型student (2) 聯(lián)合類型student(3) 結(jié)構(gòu)變量student (4) 數(shù)組類型student
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 公司策劃活動方案
- 公司每天晨跑活動方案
- 2025年心理咨詢與心理治療基礎(chǔ)知識考試試題及答案
- 2025年市場營銷策劃考試試題及答案
- 2025年時(shí)尚設(shè)計(jì)師職業(yè)資格考試試卷及答案
- 2025年攝影師職業(yè)技能測試試題及答案
- 2025年民法典相關(guān)知識的考試試題及答案
- 2025年城市交通與環(huán)境問題分析考試試題及答案
- 2025年中國冷壓香皂行業(yè)市場全景分析及前景機(jī)遇研判報(bào)告
- 二型糖尿病的護(hù)理
- 2025年山東夏季高中學(xué)業(yè)水平合格考模擬生物試卷(含答案)
- 大連海事大學(xué)育鯤輪電機(jī)員培訓(xùn)課件詳解
- GB/T 45577-2025數(shù)據(jù)安全技術(shù)數(shù)據(jù)安全風(fēng)險(xiǎn)評估方法
- IgG4腎病的診斷和治療
- 中國啤酒籃行業(yè)市場發(fā)展前景及發(fā)展趨勢與投資戰(zhàn)略研究報(bào)告2025-2028版
- 2025年中國直接結(jié)合鎂鉻磚數(shù)據(jù)監(jiān)測研究報(bào)告
- 會議流程規(guī)劃能力試題及答案
- 中藥硬膏熱貼敷操作流程
- 西安歷年美術(shù)中考題及答案
- 國家開放大學(xué)《管理學(xué)基礎(chǔ)》形考任務(wù)1-4答案
- 眩暈中醫(yī)臨床路徑解讀
評論
0/150
提交評論