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

C語言結構體進階:定義、初始化、賦值、指針訪問、柔性數組與對齊實戰

     編輯:關於C語言

結構體是 C 語言組織異構數據的核心機制。本文從定義語法、初始化規則、賦值語義、指針訪問三種形式、柔性數組成員、對齊實測六個維度,構建結構體完全使用手冊。

1. 定義與標籤

// 帶標籤:可自引用、跨文件聲明
struct Book {
    int price;
    char title[44];
};

// 無標籤:僅能在定義時同時聲明變量
struct { int x; int y; } point;

2. 變量聲明與初始化

// 聲明
struct Book b1, b2;

// 初始化:順序匹配、指定初始化器 (C99)
struct Book b3 = { 50, "C Primer" };
struct Book b4 = { .title = "Modern C", .price = 80 };

// 部分初始化:其餘字段自動置 0
struct Book b5 = { .price = 30 };  // title 全 \0

// 全局/靜態變量必須常量表達式初始化
static struct Book g_book = { 100, "Global" };

3. 賦值語義:結構體可直接賦值 (淺拷貝)

struct Book a = {1, "A"}, b;
b = a;  // 合法:逐字節拷貝所有成員 (指針成員拷貝地址)

// ❌ 不能用賦值列表:b = {2, "B"}; // 僅初始化時允許
// ❌ 不能比較:if (a == b) // 錯誤

4. 成員訪問:三種形式等價

struct Book book = {20, "Effective C"};
struct Book *ptr = &book;

// 1. 直接訪問
book.price = 25;

// 2. 指針箭頭操作符 (最常用)
ptr->price = 30;

// 3. 解引用後點操作符
(*ptr).price = 35;

// 遞歸結構體
struct Node { int val; struct Node *next; };
struct Node n1 = {1, NULL}, n2 = {2, &n1};
n2.next->val;  // 1

5. 柔性數組成員 (C99) — 變長結構體神技

struct Packet {
    uint16_t len;
    uint8_t  data[];  // 無大小,必須為最後一個成員
};

// 分配:結構體 + 可變數據
struct Packet *pkt = malloc(sizeof(struct Packet) + 100);
pkt->len = 100;
memcpy(pkt->data, payload, 100);

// 釋放單次 free 即可
free(pkt);

優勢:單次分配、緩存局部性佳、無雙重指針間接訪問。

6. 對齊與 sizeof 實測

#include <stdio.h>

struct A { char c; int i; short s; };   // 12 字節 (x86-32)
struct B { char c; short s; int i; };   // 8 字節
struct C { double d; int i; };          // 16 字節 (double 8 對齊)

int main() {
    printf("A=%zu B=%zu C=%zu\n", sizeof(struct A), sizeof(struct B), sizeof(struct C));
    // 輸出: A=12 B=8 C=16
    return 0;
}

7. 位域 — 壓縮標誌位

struct Flags {
    unsigned int ready : 1;
    unsigned int error : 1;
    unsigned int mode  : 2;  // 0-3
    unsigned int reserved : 28;
};  // 總共 4 字節

struct Flags f = {1, 0, 2, 0};
if (f.ready) { /* ... */ }

8. 避坑速查

錯誤後果修正
結構體定義末尾漏分號編譯錯誤/後續聲明解析異常加分號
柔性數組非最後一個成員編譯錯誤移至末尾
指針成員賦值後雙方 freeDouble Free明確所有權/引用計數
直接比較結構體變量編譯錯誤逐字段比較或 memcmp (注意填充字節)
跨平台傳輸結構體未處理對齊/端序數據解析錯誤#pragma pack + hton/ntoh 序列化

9. 最佳實踐清單

  1. 首選 struct Tag { ... }; + typedef struct Tag TypeName; 分離定義。
  2. 初始化用指定初始化器 { .field = val },抗重構。
  3. 指針成員明確所有權註釋:// owned / // borrowed。
  4. 網絡/存儲結構體加 #pragma pack(1) 並手動處理端序。
  5. 大型結構體傳參用 const Struct*,避免棧拷貝開銷。

結構體看似簡單,實則承載著內存佈局控制、類型系統邊界、序列化契約、所有權語義等系統級關鍵決策。精通結構體,即精通 C 語言的數據建模核心。

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