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

C語言結構體完全指南:定義、使用、數組與指針進階

     編輯:關於C語言

結構體:自定義複合數據類型

結構體 將不同類型的變量組合為單一實體,是 C 語言構建複雜數據模型的基石。每個成員擁有獨立名稱與內存位置,同時存在(與聯合體對比)。

一、定義與聲明的多種形式

1. 定義同時聲明變量

struct Person {
    char name[20];
    int age;
    float salary;
} p1, p2; // 直接定義兩個變量

2. 僅聲明標籤,後續定義變量

struct Person { /* ... */ }; // 聲明標籤 Person
struct Person p1, p2;          // 定義變量
struct Person arr[100];        // 結構體數組

3. 匿名結構體(僅定義變量,無標籤)

struct {
    char name[20];
    int age;
} p1, p2; // 無法在別處復用此類型

4. typedef 簡化類型名

typedef struct {
    char name[20];
    int age;
} Person; // 現在 Person 是類型別名

Person p1, p2; // 直接使用,無需 struct 關鍵字

二、成員訪問與操作

1. 直接訪問 (.)

struct Person p = {"Alice", 25, 5000.0f};
printf("Name: %s, Age: %d\n", p.name, p.age);
p.salary += 1000;

2. 指針訪問 (->)

struct Person *ptr = &p;
printf("%s\n", ptr->name); // 等價於 (*ptr).name
ptr->age++;

3. 結構體賦值與比較

  • 支持整體賦值(逐成員拷貝,淺拷貝)。
  • 不支持直接比較(p1 == p2 非法),需逐成員比較或 memcmp(注意填充字節)。

三、結構體數組:批量管理同類實體

struct Student {
    char name[20];
    int id;
    float gpa;
} class[50];

// 初始化
struct Student class[3] = {
    {"Alice", 1001, 3.8},
    {"Bob", 1002, 3.5},
    {"Carol", 1003, 3.9}
};

// 遍歷
for (int i = 0; i < 3; i++) {
    printf("%s: %.2f\n", class[i].name, class[i].gpa);
}

四、結構體指針:動態分配與鏈式結構

1. 動態分配單個結構體

struct Node *p = malloc(sizeof(struct Node));
if (!p) return NULL;
p->data = 10;
p->next = NULL;

2. 指向結構體數組的指針

struct Student *ptr = class; // 指向首元素
ptr++; // 移動到下一個 Student
printf("%s\n", ptr->name);

3. 自引用結構體:鏈表/樹的核心

struct ListNode {
    int data;
    struct ListNode *next; // 必須用 struct ListNode*,不可用 typedef 別名(聲明未完成)
};

五、進階特性與最佳實踐

1. 位域:精確控制位級佈局

struct Flags {
    unsigned int ready : 1;
    unsigned int error : 1;
    unsigned int mode  : 2; // 0-3
    unsigned int reserved : 28;
} flags;

flags.ready = 1;
if (flags.error) handleError();

應用:硬件寄存器映射、網絡協議頭、壓縮標誌存儲。

2. 柔性數組成員 (C99)

struct Buffer {
    size_t len;
    char data[]; // 最後一個成員,無大小
};

struct Buffer *buf = malloc(sizeof(struct Buffer) + 100);
buf->len = 100;
// buf->data 可用 100 字節

替代傳統「結構體 + 指針 + 額外 malloc」模式,單次分配,局部性更好。

3. 對齊與填充

struct A { char c; int i; }; // 大小通常 8:c + 3填充 + i
struct B { int i; char c; }; // 大小通常 8:i + c + 3填充
// 優化:按類型大小降序排列成員,減少填充

4. 結構體傳參策略

  • 小結構體(≤ 16-32 字節):值傳遞,利用寄存器,無間接開銷。
  • 大結構體:const 指針傳遞,避免棧拷貝。
  • 需修改:非 const 指針。

六、經典錯誤與避坑

錯誤後果修正
忘記分號結尾 }語法錯誤,誤導後續聲明習慣加分號
自引用用 typedef 名編譯錯誤用 struct Tag*
結構體指針未初始化野指針崩潰分配後檢查 NULL
柔性數組非最後成員編譯錯誤放在結尾
直接比較結構體編譯錯誤逐成員或 memcmp

總結

結構體是 C 語言數據建模的核心工具。從基本定義到位域、柔性數組、對齊優化,掌握其記憶體佈局與操作語義,能編寫出高效、清晰、可維護的系統級代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved