跳轉到內容

C 程式設計/高階資料型別

來自華夏公益教科書,開放的書本,開放的世界
Clipboard

待辦事項
新增關於遞迴和迴圈相互包含資料結構的資訊和部分。


上一節: 開始練習 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.iu.d,但不能同時訪問兩者。由於 u.iu.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 中模擬關聯陣列。

上一節: 開始練習 C 程式設計 下一節: 指標和陣列
華夏公益教科書