C 程式設計/高階資料型別
在章節 變數 中,我們討論了基本資料型別。然而,高階 資料型別允許我們在程式中更靈活地管理資料。
結構體是由其他資料型別變數(可能包括其他結構體)組成的。它們用於將資訊片段分組為有意義的單元,並允許一些其他方式無法實現的結構。在結構體中宣告的變數稱為“成員”。使用struct關鍵字定義結構體。例如
struct mystruct {
int int_member;
double double_member;
char string_member[25];
} struct_var;
struct_var 是一個struct mystruct 型別的變數,我們是在定義新的struct mystruct 資料型別時一起宣告的。更常見的是,在定義結構體之後使用以下形式宣告結構體變數
struct mystruct struct_var;
通常的做法是建立一個類型別名,這樣我們就不必一直輸入“struct mystruct”。C 允許我們使用typedef 語句來做到這一點,它為型別建立別名
typedef struct {
// ...
} Mystruct;
struct 本身是一個不完整的 型別(因為第一行沒有名稱),但它被指定為Mystruct 的別名。然後可以使用以下方法
Mystruct struct_var;
可以使用成員訪問運算子.(點號)或間接成員訪問運算子->(箭頭)訪問結構體變數的成員,如果結構體變數是指標
struct_var.int_member = 0;
struct_var->int_number = 0; // this statement is equivalent to: (*struct_var).int_number = 0;
(指標將在下一章中解釋)。結構體不僅可以包含自己的變數,還可以包含指向其他結構體的變數。這允許遞迴定義,當與指標一起使用時非常強大
struct restaurant_order {
char description[100];
double price;
struct restaurant_order *next_order;
};
這是 連結串列 資料結構的實現。每個節點(餐廳訂單)都指向另一個節點。連結串列在最後一個節點(在我們的示例中,這將是最後一個訂單)處終止,其next_order 變數將被分配給NULL。
當與typedef一起使用時,遞迴結構定義可能很棘手。無法透過使用其指定定義在自己的型別中宣告結構體變數,因為在typedef語句被評估之前,指定定義不存在
typedef struct Mystruct {
// ...
struct Mystruct *pointer; // Mystruct *pointer; would cause a compile-time error
} Mystruct;
結構體型別的尺寸至少是所有成員尺寸的總和。但是編譯器可以自由地在結構體成員之間插入填充位元組,以使成員對齊到某些約束。例如,在許多 32 位架構中,包含一個字元和一個浮點數的結構體將佔用 8 個位元組。
聯合體的定義類似於結構體的定義。兩者之間的區別在於,在結構體中,成員佔用記憶體的不同區域,而在聯合體中,成員佔用記憶體的相同區域。因此,在以下型別中,例如
union {
int i;
double d;
} u;
程式設計師可以訪問u.i 或u.d,但不能同時訪問兩者。由於u.i 和u.d 佔用記憶體的相同區域,修改其中一個會修改另一個的值,有時以不可預測的方式。這也是聯合體在實踐中很少見的主要原因。
聯合體的尺寸是其最大成員的尺寸。
列舉是人工資料型別,表示標籤和整數之間的關聯。與結構體或聯合體不同,它們不包含其他資料型別。一個示例宣告
enum color {
red,
orange,
yellow,
green,
cyan,
blue,
purple,
} crayon_color;
在上面的示例中,red 等於 0,orange 等於 1,... 等等。可以在整數範圍內為標籤分配值,但它們必須是字面量。
適用於結構體和聯合體的類似宣告語法也適用於列舉。此外,通常不需要關心標籤所代表的整數
enum weather weather_outside = rain;
這種特殊的特性使得列舉在 switch-case 語句中特別方便
enum weather {
sunny,
windy,
cloudy,
rain,
} weather_outside;
// ...
switch (weather_outside) {
case sunny:
wear_sunglasses();
break;
case windy:
wear_windbreaker();
break;
case cloudy:
get_umbrella();
break;
case rain:
get_umbrella();
wear_raincoat();
break;
}
列舉是模擬 C 中關聯陣列的簡化方式。
