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

C 語言共用體完整指南:共享記憶體、型別轉換與實務應用

     編輯:C 語言入門

C 語言共用體深度解析:記憶體共享、型別重疊與進階技巧

共用體(Union)是 C 語言特有的資料結構,允許不同型別的成員共享同一塊記憶體空間。任一時刻僅有一個成員持有有效值,大小等於最大成員的大小。廣泛應用於型別轉換、硬體暫存器存取、資料序列化、節省記憶體等場景。本文詳細說明定義、存取規則、記憶體模型、常見陷阱與實務範例。

定義與基本語法

union [標籤] {
    成員定義;
    成員定義;
    ...
} [變數列表];

範例:定義可儲存整數、浮點數或字串的 Data 型別:

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

data 佔用 20 位元組(str[20] 最大)。

記憶體大小驗證

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

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

int main() {
    union Data data;
    printf("Memory size occupied by data : %zu\n", sizeof(data));
    return 0;
}

輸出:

Memory size occupied by data : 20

成員存取與值覆蓋行為

使用成員存取運算子 .(或指標用 ->)。關鍵特性:寫入一個成員會覆蓋其他成員的位元模式。

錯誤示範:同時使用多個成員

union Data data;
data.i = 10;
data.f = 220.5;
strcpy(data.str, "C Programming");

printf("data.i : %d\n", data.i);      // 1917853763 (垃圾值)
printf("data.f : %f\n", data.f);      // 4122360580327794860452759994368.000000 (垃圾值)
printf("data.str : %s\n", data.str);  // C Programming (正確,最後寫入)

只有最後寫入的 str 保持有效,前兩者因位元模式被覆蓋而成為無意義值。

正確用法:同一時間僅使用一個成員

union Data data;
data.i = 10;
printf("data.i : %d\n", data.i);      // 10

data.f = 220.5;
printf("data.f : %f\n", data.f);      // 220.500000

strcpy(data.str, "C Programming");
printf("data.str : %s\n", data.str);  // C Programming

每次僅讀取最近寫入的成員,所有輸出皆正確。

進階應用:型別轉換與位元檢視

共用體是合法的型別雙關,可用於檢視浮點數位元模式、整數位元組分解等:

浮點數 IEEE 754 位元分析

union FloatBits {
    float f;
    unsigned int bits;
};

void print_float_bits(float val) {
    union FloatBits fb;
    fb.f = val;
    printf("Value: %f, Hex: 0x%08X\n", fb.f, fb.bits);
    // 進一步解析:sign = bits>>31, exp = (bits>>23)&0xFF, mantissa = bits&0x7FFFFF
}

整數位元組序檢測

union EndianTest {
    uint32_t i;
    uint8_t c[4];
};

bool is_little_endian() {
    union EndianTest test;
    test.i = 0x01020304;
    return test.c[0] == 0x04;  // 低位元組在低位址
}

匿名共用體(C11)

結構體中可嵌入無標籤共用體,成員直接提升至結構體作用域:

struct Packet {
    uint16_t header;
    union {
        struct { uint8_t cmd; uint8_t len; } control;
        struct { uint32_t addr; uint16_t port; } data;
    };
    uint16_t crc;
};

// 存取:pkt.cmd, pkt.addr 等,無需 pkt.u.cmd

常見陷阱與最佳實務

陷阱說明對策
讀取非作用中成員行為未定義(C 標準),產生垃圾值嚴格遵守「寫入後立即讀取同一成員」
對齊需求差異成員對齊要求可能導致共用體大小大於最大成員使用 alignas (C11) 或編譯器屬性控制對齊
跨平台資料交換位元組序、填充、大小皆可能不同序列化時明確處理端序,避免直接傳輸共用體
嚴格別名規則違反透過共用體進行型別雙關在 C99/C11 為合法,但 C++ 不同C 程式碼中合法使用;混合 C/C++ 專案需謹慎

共用體 vs 結構體:核心差異

特性結構體共用體
記憶體配置成員依序排列,大小為總和(含填充)成員重疊共享,大小為最大成員
同時有效成員所有成員僅一個
典型用途資料聚合、記錄表示型別轉換、互斥資料、記憶體節省

總結

共用體是 C 語言底層記憶體操作的核心工具,提供型別重疊與記憶體共享能力。正確使用需遵守「單一作用成員」原則,並深度理解目標平台記憶體模型。在嵌入式開發、系統程式、高效能序列化等領域,共用體是不可或缺的進階技術。

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