首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言構造類型全解析:枚舉、結構體、類型定義與進階用法

     編輯:關於C語言

C 語言用戶定義類型:enum、struct、typedef 系統性掌握

構造類型讓 C 突破基本類型限制,建模現實世界實體。本文涵蓋枚舉自動計數、結構體初始化/指針/嵌套/數組、位域、柔性數組、typedef 別名與不透明指針等核心知識點。

一、枚舉:命名整數常量集合

enum Color { RED, YELLOW, GREEN, NUM_COLORS }; // 值 0,1,2,3
enum Status { OK = 0, ERR_IO = -1, ERR_MEM = -2 }; // 可指定值
  • 本質是 int 常量,編譯期常量,可用作數組大小、switch case。
  • 技巧:末尾添加 NUM_COLORS 自動獲得元素個數,便於邊界檢查。
  • 類型安全:C 允許枚舉隱式轉換為 int,但不同枚舉類型間賦值會警告(C++ 更嚴格)。

二、結構體:異構數據聚合

1. 聲明與定義

// 帶標籤聲明(推薦)
struct Point { int x, y; };
struct Point p1, p2; // 定義變量

// 匿名結構體直接定義變量(無法復用類型)
struct { int x, y; } p3, p4;

2. 初始化多樣化

struct Date { int year, month, day; };
struct Date d1 = {2024, 5, 20};           // 順序初始化
struct Date d2 = {.month = 5, .year = 2024}; // C99 指定初始化器,未指定字段自動 0
struct Date d3 = {.day = 1};               // year=0, month=0, day=1

3. 結構體指針與 -> 運算符

struct Date *pd = &d1;
pd->year = 2025;   // 等價於 (*pd).year = 2025
// 注意:結構體變量名不是地址,必須用 & 取地址

4. 函數傳遞:值傳遞 vs 指針傳遞

  • 值傳遞:函數內創建副本,修改不影響原值,開銷大(大結構體)。
  • 指針傳遞:傳遞地址,可修改原值,高效。const struct Date * 表示只讀。
  • 返回結構體:C99 允許直接返回結構體值(編譯器優化通常無拷貝開銷)。

5. 實戰案例:日期運算(計算明天)

bool is_leap(struct Date d) {
    return (d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0;
}
int days_in_month(struct Date d) {
    static const int days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    return (d.month == 2 && is_leap(d)) ? 29 : days[d.month - 1];
}
struct Date tomorrow(struct Date today) {
    struct Date tm = today;
    if (++tm.day > days_in_month(tm)) {
        tm.day = 1;
        if (++tm.month > 12) { tm.month = 1; tm.year++; }
    }
    return tm;
}

6. 結構體數組

struct Time { int h, m, s; };
struct Time tests[5] = { {11,59,59}, {12,0,0}, {1,29,29}, {23,59,59}, {19,12,27} };
// 遍歷修改:tests[i] = time_update(tests[i]);

7. 嵌套結構體

struct DateTime { struct Date date; struct Time time; };
struct Rectangle { struct Point pt1, pt2; };
// 訪問:rect.pt1.x 或 rp->pt1.x (rp 指針)
// 注意:pt1 非指針,無 rp->pt1->x

三、typedef:類型別名與封裝

typedef struct { int x, y; } Point; // 匿名結構體 + typedef
Point p = {1, 2}; // 直接用類型名,無需 struct 關鍵字

// 函數指針別名
typedef int (*Comparator)(const void *, const void *);
// 不透明指針(頭文件隱藏實現)
typedef struct Opaque *OpaqueHandle;
  • 區別:typedef 創建類型別名,#define 是文本替換;typedef 受作用域約束,支持指釖類型組合。
  • 慣例:結構體標籤用 PascalCase (struct Date),typedef 名用 snake_case (date_t) 或同名 (Date)。

四、進階特性

五、最佳實踐清單

  • ✅ 結構體定義放在頭文件,配合 typedef 簡化使用。
  • ✅ 大結構體傳遞用 const struct T *,小結構體 (≤ 2-3 字) 可值傳遞。
  • ✅ 使用指定初始化器 {.field = val} 提高可讀性與抗重構能力。
  • ✅ 柔性數組替代傳統「結構體 + 指針」模式,單次分配提高緩存局部性。
  • ❌ 避免深層嵌套結構體導致訪問鏈過長(a.b.c.d.e)。
  • ❌ 結構體比較勿用 memcmp(填充字節不可預測),逐字段比較或生成哈希。

精通枚舉建模狀態機、結構體組織異構數據、typedef 構建類型抽象層,是編寫清晰、高效、可維護 C 代碼的核心技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性語法用途
位域struct { unsigned int flag:1; unsigned int id:7; };硬件寄存器映射、緊湊標志位存儲
柔性數組成員 (C99)struct { size_t len; char data[]; };動態大小結構體,malloc(sizeof(Header) + n) 分配
對齊控制_Alignas(16) struct { ... }; (C11)SIMD 優化、硬件對齊要求
匿名聯合體/結構體 (C11)union { struct {int x,y;}; struct {int w,h;}; };同一內存多種視圖,字段直接訪問