跳轉到內容

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

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

待辦事項
新增有關遞迴和迴圈相互包含資料結構的資訊和章節。


上一篇:開始練習 C 程式設計 下一篇:指標和陣列

在章節 變數 中,我們瞭解了基本資料型別。然而,高階資料型別使我們能夠在程式中更靈活地管理資料。

結構體

[編輯 | 編輯原始碼]

結構體是資料型別,由其他資料型別的變數組成(可能包括其他結構體)。它們用於將資訊片段分組為有意義的單元,並允許某些其他方式無法實現的構造。在結構體中宣告的變數稱為“成員”。可以使用struct關鍵字定義結構體。例如

struct mystruct {
    int int_member;
    double double_member;
    char string_member[25];
} struct_var;

struct_varstruct 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 程式設計 下一篇:指標和陣列
華夏公益教科書