第14章結構體、共用體、枚舉和typedef_第1頁
第14章結構體、共用體、枚舉和typedef_第2頁
第14章結構體、共用體、枚舉和typedef_第3頁
第14章結構體、共用體、枚舉和typedef_第4頁
第14章結構體、共用體、枚舉和typedef_第5頁
已閱讀5頁,還剩27頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、第14章 結構體、共用體、枚舉和typedef 程序設計中,如何合理組織數據是門大學問,前面介紹過的數組是種組織數據的方式,但數組只適用于同類型的數據,如果類型不同又當如何?而且,現實中,很多東西都具有不同的屬性,以人為例,像姓名、性別、身高等等都是其屬性,如何合理存儲并方便地訪問這些信息,是本章介紹的內容。14.1 什么是結構體 仍以人為例來介紹,要管理姓名、單位、Email地址、聯系電話等信息,現實生活中,很多人采用名片的形式,將這些信息印在一張卡片上。收集的一張張名片大大方便了數據的管理,將這種理念借鑒到C語言程序設計中,是否有類似于名片的那么一種變量呢? 有,答案就是“結構體變量”,是

2、一種復合變量,在進一步說明結構體變量前,先來看“結構體”的概念,結構體和結構體變量的關系類似與類型與普通變量的關系,結構體中說明了結構體變量的信息格式,而結構體變量是結構體的實例。14.1.1 結構體的定義只有定義了一個結構體,才能聲明并使用結構體變量,正如,只有確定了名片上要印什么內容,才能開始印刷名片。結構體的定義就是說明結構體變量要存儲什么信息的過程。C語言提供了關鍵字struct來定義一個結構,一般形式的結構定義為:struct 結構名稱(或稱標識)存儲數據列表;(或稱成員變量列表);注意:在定義結構時,一定不要忘記花括號后的分號,因為結構的定義可以看成一條完整的C+語句,否則編譯器會

3、報錯。舉例來說,struct personchar name20;int age;char email50;14.1.2 聲明結構體變量以上面person結構為例,定義完畢后,person就可以看成是一種類型,可以通過下述形式聲明結構體變量zangsan:struct person zangsan;注意區分person和zangsan,person只是結構體定義,是種規范說明,編譯器并不為其分配內存空間,而zangsan是實實在在的結構體變量,占據一定的內存空間。在定義結構體的同時也可以完成一個或多個結構體變量的聲明,舉例來說:struct personchar name20;int age;

4、char email50;zangsan,lisi,wangwu,*zaoliu;上述代碼在定義結構體person的同時,一口氣聲明了3個結構體變量:zangsan,lisi,wangwu,甚至還聲明了一個指向person結構的指針zaoliu。14.1.3 初始化結構變量在聲明結構變量的同時,可以進行變量的初始化,對結構體中每個數據初始化,用逗號隔開,并用花括號包裹起來,舉例來看:struct person zangsan=“Zang San”, 24, “”;還可以將結構體定義,結構體變量聲明和初始化放在一起來完成,如:struct personchar name20;int age;ch

5、ar email50;zangsan=“Zang San”, 24, “”, *pzs=&zangsan;14.1.4 訪問結構體成員習慣上將諸如字符串name、int變量age和字符串email等稱為結構體person及其聲明變量的“數據成員”,簡稱“成員”。聲明了一個結構體變量后,可以使用成員操作符(.)來訪問各個成員(內部存儲的數據),如,zangsan.age和zangsan.emal分別代表zangsan這個變量(結構體變量)中存儲的姓名、年齡和email等信息,來看一段示例:代碼 訪問結構體變量中的數據成員StructSample14.1.5 結構體

6、定義的位置讀者可以做個有趣的嘗試:將中結構體定義的部分轉移到main函數的后面,重新編譯運行,會發生什么?編譯器會報一大堆的錯誤,正如“使用變量前必須先對其聲明”一樣,在使用結構體類型聲明結構體變量之前,必須要先進行結構體的定義,編譯器據此才知道如何為結構體中的數據成員分配內存空間,才能聲明結構體變量。除了如的定義方式外,結構體還可以定義在函數(包括main函數)中,兩種定義方式的區別在于結構體可見域不同,如果定義在函數外,從定義處到本文件結束,結構體都可見,可用結構體聲明結構體變量,但如果定義在特定函數中,只有定義處到該函數結束,結構體可見,如果在函數外使用結構體聲明結構體變量,可能會引發錯

7、誤。一種推薦的寫法是將結構體定義在頭文件中,只要某文件A包含了此頭文件,便可在A中自由聲明結構體變量。14.1.6 結構體變量賦值C語言不允許使用一個數組直接為另一個數組賦值,但使用一個結構體變量為另一個結構體變量賦值是合法的,可以使用賦值操作符(=)將一個結構變量B賦值給另一個結構變量A,這樣,結構變量A中的每個成員都將被設置成結構變量B中相應成員的值,即使成員是數組類型也不例外,這種賦值方式被成為成員賦值,見示:14.2 特殊結構體 上一節中討論的person結構相對簡單,只包含了3個數據成員:name、age和email,如果面對的是更為復雜的結構,將所有的數據成員并排似乎不是個高效的方

8、法,那能否使用結構體嵌套,一層層管理數據呢?14.2.1 結構體嵌套顧名思義,結構體嵌套就是“結構體套結構體”,某個結構的數據成員也是一個結構體變量,這樣,可以按層次結構合理組織數據,舉例來說:struct studentchar name20;struct scorestruct/*結構體scorestruct的定義*/int math;int English;score;/*聲明結構體變量score*/struct infostruct/*結構體infostruct的定義*/float height;float weight;info;/*聲明結構體變量info*/;14.2.2 匿名結構

9、體C語言允許定義匿名結構,所謂匿名結構,就是不指定結構體的名稱,但一定要在結構體定義的同時聲明至少一個結構體變量,否則,這種用法沒有意義,如:structchar name20;int age;wangwu, lisi;這樣便聲明創建了兩個結構體變量wangwu和lisi,可以通過諸如“”等形式來訪問其成員,但這種類型沒有名稱,因此無法在以后的程序中聲明這種類型的變量。14.3 共用體 共用體也是一種特殊的數據組織方式,C語言使用關鍵字union來定義一個共用體結構,所以,在某些書籍中也將共用體稱為“聯合”。和結構體類似,共用體的使用也分為“共用體的定義”、“共用體變量的

10、聲明、初始化和使用”兩大部分。14.3.1 什么是共用體 和結構一樣,共用體也是由數據成員組成的,但在結構中,編譯器為每個數據成員都分配內存地址空間,但對共用體來說,所有的數據成員共用一塊內存,這個“共用”似乎有些費解,理解方式應當是“在某個確定的時刻,共用體只能表示一種成員類型”。14.3.2 共用體的定義共用體可采用如下形式定義:union 共用體名稱(或稱標識)存儲數據列表(或稱成員變量列表);注意,結束花括號后的分號(;)不要遺漏,這種定義形式是一個完整的C+語句。舉例來說:union computerInfo/*定義一個共用體computerInfo*/char typeid20;f

11、loat price;某個部門要登記所有的電腦,如果是品牌機,就登記型號(typeid),如果是組裝機,就登記價格(price),因此,型號和價格只取其一,這時使用共用體最為合適。14.3.3 聲明共用體變量 和結構體的使用方式一樣,定義了共用體后,共用體名可以看成是一種類型,用其可聲明共用體變量,基本格式為: union 共用體名 共用體變量; 在定義共用體的同時也可以完成一個或多個共用體變量的聲明,舉例來說: union computerInfo/*定義一個共用體computerInfo*/ char typeid20; float price; comp1, comp2;14.3.4 共

12、用體變量的初始化在聲明一個共用體比昂兩的同時,可以完成其初始化,與結構變量的初始化不同的是,只能對共用體變量列表中的一個變量進行初始化,對前面定義的共用體computerInfo來說,下列語句是合法的:computerInfo com1=Asus X80;computerInfo com1=6000;與結構類似,可以把共用體定義、共用體變量聲明及其初始化放在一起,如:union computerInfo/*定義一個共用體computerInfo*/char typeid20;float price;comp1= Asus X80;14.3.5 共用體成員訪問不論共用體在定義時成員列表中有多少項

13、,在某個確定時刻,共用體變量只能存儲一個成員,來看一個示例: 14.3.6 共用體賦值 從本質上理解,共用體實際上是為不同的成員分配一塊共用內存,編譯器并不會約束存入這塊內存的值,關鍵在于程序員如何解析這塊內存,如何使用存入的內容。 C語言允許共用體變量間的賦值,且無論是結構體變量的賦值還是共用體變量的賦值,實際上都是內存單元的照搬復制。 14.4 結構體和共用體的內存差異 結構體變量和共用體變量是兩種復合類型的變量,對C語言內置的基本數據類型,我們都明確知道其占用的內存空間大小,但結構體變量和共用體變量占據多大的內存空間呢?兩種變量在內存中的表示形式有何差別?這是本節討論的問題。14.4.1

14、 結構體變量和共用體變量內存形式的不同前面以及提到,編譯器會為結構體變量中的每個數據成員分配不同的地址空間,也就是說,結構體變量中的數據程序是并列關系,而編譯器為共用體變量中的數據成員分配的是同一塊內存,每個時刻只有一個數據成員有意義,從地址的角度來看兩者的差異,形象地表明了這一點。14.4.2 結構體變量的內存大小直觀上理解,結構體變量占據的內存單元的個數應當是其內部所有數據成員占據內存單元數的和,但實際情況卻并非如此,來看一段:14.4.3 字節對齊 出于效率的考慮,C語言引入了字節對齊機制,一般來說,不同的編譯器字節對齊機制有所不同,但還是有以下3條通用準則: (1)結構體變量的首地址能

15、夠被其最寬基本類型成員的大小所整除; (2)結構體每個成員相對于結構體首地址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充字節(internal adding); (3)結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之后加上填充字節(trailing padding)。14.4.4 最寬基本類型字節對齊第3條準則提及最寬基本類型的概念,所謂基本類型是指像char、short、int、float、double這樣的內置數據類型?!皵祿挾取本褪侵钙鋝izeof的大小。諸如結構體、共用體和數組等都不是基本數據類型,來看一段示例:

16、14.4.5 共用體的大小原則上,共用體的大小取決于占據最多內存的成員的長度,如:union Example char c;short s;float f; 則sizeof(Example)的結果為4,但字節對齊準則3,“結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之后加上填充字節(trailing padding)”仍然成立,來看下面的共用體定義:union Examplechar c9;double d; 14.5 枚舉類型 從字面上理解,枚舉是“列舉所有情況”的意思,C語言中,枚舉類型也是這么用的,枚舉類型是種用戶自定義的類型,在定義枚舉類型時,需指

17、明其取值集合,用枚舉類型聲明枚舉變量時,只能取集合中的某項作為其值,這在一定程度上保證了取值的安全性。14.5.1 枚舉類型的定義C語言提供了關鍵字Enum定義枚舉類型,基本格式為:enum 枚舉類型名 枚舉常量1=整型常數,枚舉常量2=整型常數,;作為一條完整的C語句,不要忘記結尾的分號。枚舉類型的定義包括以下要素:枚舉類型名,有效的C語言標識符。枚舉表,即“枚舉常量1=整型常數,枚舉常量2=整型常數,”部分,枚舉表是枚舉常量的集合,枚舉表中每項后的“=整型常數”是給枚舉常量賦初值,方括號代表賦初值的操作可以省略。如果不給枚舉常量賦初值,編譯器會為每一個枚舉常量賦一個不同的整型值,第一個為0

18、,第二個為1,等等。當枚舉表中某個常量賦值后,其后的成員則按依次加1的規則確定其值。來看一個簡單的例子: enum day Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;14.5.2 聲明枚舉變量 定義了枚舉類型day后,便可聲明day型枚舉變量,如: enum day today; 上述語句聲明了day型變量today。注意,today只能取枚舉表中的某項作為其值,枚舉變量在其枚舉表成員之外取值是不允許的。 可在枚舉類型定義的同時聲明該類型的變量,如: enum day Sunday,Monday,Tuesday,Wedne

19、sday,Thursday,Friday,Saturday toay;14.5.3 枚舉常量是什么在上面定義的枚舉類型day中,諸如Monday、Tuesday等稱為枚舉常量,有個疑問:枚舉常量到底是什么?來看一段示例:代碼 枚舉常量EnumConst#include /*使用printf要包含的頭文件*/#include enum color Red,Green,Blue,Black,White;/*枚舉類型的定義*/void main(void)/*主函數*/enum color c1=Blue;printf(Blue is %d,c1);/*枚舉常量是整型*/getch();/*等待,按

20、任意鍵繼續*/輸出結果為Blue is 214.6 給類型取個別名typedef 可以給某個已經存在的類型取個別名,使其更易寫、更易記,C語言中提供了兩種方法,一是使用“#define”語句,另一個方法是使用typedef語句,兩者之間存在細微的差別。14.6.1 typedef基本用法 先來看一個直觀的例子: typedef double* DP; typedef為double* 引入了一個新的助記符DP,在程序中可使用DP聲明一個指向double型變量的指針,如: DP pDouble1, pDouble2; 上述代碼聲明了兩個double型的指針變量pDouble1和pDouble2。14.6.2 #define用法#define語句稱為預定義語句,是預處理指令,在編譯預處理時進行簡單的替換,不做正

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論