共用體
共用體,也叫聯合,有時候需要把幾種不同類型的變量存放到同一段內存單元,例如,把一個整型變量、一個字符型變量、一個字符數組放在同一個地址開始的內存單元中。這三個變量在內存中占的字節數不同,但它們都從同一個地址開始,換句話說就是幾個變量會互相覆蓋。這種幾個變量共同占用同一段內存的存儲數據的方式,就叫共用體,這些變量也被稱為共用體成員變量(簡稱“成員”)。
看一看共用體定義的一般形式:
共用體因為成員占用同一段內存,所以占用的內存大小等于占用內存最大的成員所占的內存大小,而不是每個成員所占內存大小之和。
有幾點說明:
(1)共用體變量的引用方式。和結構體很類似,不能直接引用共用體變量,只能引用共用體變量中的成員,如a.cname、a.carnum,要知道,a對應的內存空間中有好幾種不同類型的成員,每個成員占的內存大小都可能不同,所以必須明確寫明引用的成員。
(2)共用體變量的特點。同一段內存中存放幾個不同類型的成員,但每一個瞬間只能存放其中一個,換句話說,每個瞬間只能有一個成員起作用,其他成員不起作用。
程序中最后給哪個成員賦值,哪個成員就起作用。看如下代碼:
所以,使用共用體變量時必須時刻注意當前存放在其中的數據,明確知道哪個成員當前正在起作用。
(3)共用體變量地址和其成員的地址都相同。也就是說,&a、&a.carnum、&a.cartype、&a.cname所代表的首地址都相同,共用體變量名也代表共用體變量的首地址,這一點與數組名代表數組首地址的說法類似。
(4)共用體變量不能在定義的時候給所有成員都進行初始化。看如下代碼:
但是在定義的時候初始化第一個成員是允許的。看如下代碼:
枚舉類型
如何理解枚舉類型?例如有4種顏色,分別是紅色、綠色、藍色、黃色,現在想表示這4種顏色,可以約定用數字來表示,如約定0表示紅色,1表示綠色,2表示藍色,3表示黃色,這當然可以,但0、1、2、3這樣的數字看起來很不直觀,如果能夠用一些英文單詞如用Red表示紅色,Green表示綠色,Blue表示藍色,Yellow表示黃色,更直觀、更容易讓人看懂,此時枚舉類型就能發揮作用。看看怎樣用枚舉類型來定義這些顏色,代碼如下:
enum color //color是枚舉類型名
{Red, //值Green,Blue,Yellow
};
這樣就定義了一個名字叫作color的枚舉類型,因為這是個類型,定義完之后,就可以使用這個類型了。看看如下代碼:
有幾點說明:(1)枚舉,就是將值一一列舉出來,那么上面的變量mycolor1、mycolor2的值只限于列舉出來的這些值的范圍內,也就是Red、Green、Blue、Yellow之一(當然后續還有mycolor1、mycolor2不限于這些值范圍的講述,后續再說)。例如:
(2)可以直接定義枚舉類型變量,不需要寫枚舉類型名。看看如下代碼:
(3)Red、Green、Blue、Yellow,這些叫作枚舉常量,記住,它們是常量,用來給枚舉型變量賦值,那么這些枚舉型常量所代表的值是多少呢?C語言編譯器會按照它們定義時的順序規定它們的值,并且值是從0開始,這說明,Red等于0、Green等于1、Blue等于2、Yellow等于3。看看如下代碼:
(4)可以直接給枚舉型變量賦值。看看如下代碼:
(5)定義枚舉類型時,可以改變默認的枚舉常量的值(默認的枚舉常量值前面說過是從0開始)。看看如下代碼:
(6)枚舉值,可以理解為整型值,只是在實際寫代碼時,有時寫枚舉值更容易讓人懂,但不能把一個整數直接賦給一個枚舉變量。看看如下代碼:
但用強制類型轉換是可以的:
這可能讓人好奇,1000這個數字并不對應于枚舉類型color中的任何一個枚舉型常量值,但像上面這樣寫代碼依然沒有任何問題,mycolor1被成功賦予1000這個值,這進一步證明,枚舉值其實是可以和整型值互通使用的。
此外,枚舉值也可以進行比較判斷操作:
(7)枚舉值可以賦值給一個整型變量。看看如下代碼:
用typedef定義類型
以往,代碼中用的類型名都是C語言提供的標準類型名,如int、char、float、double等,當然,結構體、共用體、枚舉類型等可以自己命名。此外,還可以用typedef關鍵字來定義新的類型名以代替已有的類型名。注意,typedef是用來定義新類型名的,不是用來定義變量的。
看看如下代碼:
這相當于用INTEGER代表了int,那么定義整型變量就可以這樣定義:
也可以用typedef定義一個結構體類型:
上面這段代碼定義了一個新的類型名DATE(不是定義結構體變量,因為前面有typedef關鍵字
),代表上面定義的這個結構體類型。現在,可以用DATA來定義變量了。看看如下代碼:
針對typedef的用法,還有一些變形,這些變形可以適當記一記,以后也許會遇到:
這里有一些重要說明,請注意:
(1)習慣上把用typedef定義的類型名用大寫字母表示,以便區別于C語言提供的標準類型標識符,如int、char等。
(2)typedef是用來定義各種類型名的,不是用來定義變量的,這一點一定不能搞錯。
(3)typedef只是對已經存在的類型增加一個類型名(相當于給類型起一個別名),并沒有創造新類型。
(4)typedef是編譯時處理的。
一個項目可以由一個或者多個源程序文件組成,一個項目可以通過編譯、鏈接最終形成一個可執行文件。而編譯這個步驟可以拆開來看,它實際也是做了好幾件事情,包括:
· 預處理:#define、#include、#ifdef;
· 編譯:詞法和語法分析、目標代碼生成、優化、typedef;
· 匯編:產生.o(.obj)目標文件。
(5)typedef最主要的作用是什么?其最主要的作用是有利于程序的通用性與可移植性。
例如以往這樣定義int型變量:
將來如果想將所有int型變量都變成long型變量,就得找到所有int型變量定義的位置并逐個修改。但如果這樣寫代碼定義,首先用一個typedef,如下所示:
然后在定義整型變量時不使用int來定義,而是使用INTEGER來定義。例如:
那以后若需要把int修改為long,只需要修改typedef這一行。例如:
這樣所有的int類型變量就都被修改為long類型。