C 語言結構、聯合與枚舉 (Structs, Unions & Enums)

C 語言允許我們自定義資料型態,讓程式碼更具可讀性且更能描述真實世界的物件。本章將介紹三種自定義型態:struct, union 以及 enum

結構 (Structure)

陣列只能儲存相同型態的資料。但如果我們想描述一個「人」,需要名字 (char array)、年齡 (int)、身高 (float),這時候就需要 Structure (結構)

定義與宣告

#include <stdio.h>
#include <string.h>

// 定義一個 Person 結構
struct Person {
    char name[20];
    int age;
    float height;
};

int main() {
    // 宣告一個 Person 變數
    struct Person p1;

    // 存取結構的成員 (Member) 使用小數點 (.)
    p1.age = 25;
    p1.height = 175.5;
    strcpy(p1.name, "John"); // 字串不能直接賦值

    printf("Name: %s, Age: %d\n", p1.name, p1.age);

    return 0;
}

結構指標

如果我們要用指標指向結構,存取成員要用箭頭 ->

struct Person p1 = {"Alice", 18, 160.0};
struct Person* ptr = &p1;

printf("Name: %s\n", ptr->name); // 等同於 (*ptr).name

聯合 (Union)

union 的寫法跟 struct 很像,但所有的成員共用同一塊記憶體。這意味著同一時間只能儲存其中一個成員的值,且記憶體大小等於最大成員的大小。

union Data {
    int i;
    float f;
    char str[20];
};

int main() {
    union Data data;

    data.i = 10;
    // 此時 data.f 和 data.str 的值是沒有意義的 (垃圾值)
    
    data.f = 3.14;
    // 此時 data.i 的值會被 data.f 覆蓋
    
    printf("data.f: %f\n", data.f);
    return 0;
}

Union 通常用於節省記憶體,或是需要對同一塊記憶體進行不同型態解讀的底層操作。

枚舉 (Enumeration)

枚舉 (enum) 用來定義一組具名的整數常數。它能讓程式碼變得更有意義,不用再面對一堆看不懂的魔術數字 (Magic Numbers)。

使用方式

// 定義一個代表星期的 enum
// 預設從 0 開始:MON=0, TUE=1, WED=2 ...
enum Week { MON, TUE, WED, THU, FRI, SAT, SUN };

// 也可以手動指定數值
enum Status { 
    OK = 200, 
    NOT_FOUND = 404, 
    ERROR = 500 
};

int main() {
    enum Week today = FRI;
    
    if (today == FRI) {
        printf("今天是星期五!(%d)\n", today); // 輸出 4
    }
    
    return 0;
}

為什麼要用 enum?

比較以下兩段程式碼:

// 不好:意義不明的數字
int status = 1; 

// 好:一看就知道狀態是什麼
enum State { STOPPED, RUNNING, PAUSED };
enum State current_state = RUNNING;

型態別名 (typedef)

typedef 可以幫資料型態取一個新名字,讓我們少打字,配合 structenum 使用特別方便。

// 定義同時取別名
typedef struct {
    int x;
    int y;
} Point;

typedef enum {
    RED, GREEN, BLUE
} Color;

int main() {
    Point p1 = {10, 20};
    Color c = RED;
    return 0;
}

掌握這三種工具,你就能設計出結構清晰、語意明確的資料模型。