共用体(union,亦称共同体)的语法形式与结构体相近,但内存布局不同:结构体各成员占用各自的存储;共用体的所有成员共享同一段存储,共用体的大小一般等于最大成员的大小(可能含对齐填充)。在实际开发中,共用体多用于在几种互斥数据之间复用同一块内存以节省空间(例如带类型标记的变体字段),或与协议报文、硬件寄存器等需要“同一地址按不同类型解读”的场景;使用时须由程序逻辑保证当前访问的成员与真实数据含义一致。

共用体的基本行为

对某一成员赋值后,其他成员原先的内容会被覆盖;同一时刻通常只应把其中一个成员视为有效。访问成员仍使用点运算符 .。

C 语言共用体基础用法示例运行
#include <stdio.h>

union Student {
    int rollNo;
    float height;
    char firstLetter;
};

int main(void) {
    union Student data;

    data.rollNo = 21;
    printf("%d\n", data.rollNo);

    data.height = 5.2f;
    printf("%.2f\n", data.height);   /* rollNo 的内容已被覆盖 */

    data.firstLetter = 'N';
    printf("%c\n", data.firstLetter);
    return 0;
}
共享内存 大小 = 最大成员(4 字节) rollNo (int) height (float) firstLetter (char) 给一个成员赋值,会覆盖其他成员的值
结构体成员各占独立空间;共用体成员映射到同一块内存,同时仅一个成员语义有效。

共用体的大小

union A {
    int x;
    char y;
};

union B {
    int arr[10];
    char y;
};

printf("Sizeof A: %zu\n", sizeof(union A));
printf("Sizeof B: %zu\n", sizeof(union B));

较小成员可存放在为最大成员预留的空间内,不会单独再占一份与最大成员等大的区域。

示例:按字节查看整数

C 语言共用体内存共享示例运行
union intParts {
    int theInt;
    char bytes[sizeof(int)];
};

union intParts parts;
parts.theInt = 5968145;

printf("整数是 %d\n", parts.theInt);
printf("四个字节分别是 [%d, %d, %d, %d]\n",
       parts.bytes[0], parts.bytes[1],
       parts.bytes[2], parts.bytes[3]);

共用体为同一存储提供了多种“视图”,避免手动进行指针类型转换。

节省空间:带类型标识的共用体

若某对象在逻辑上只可能是整数或浮点数之一,用结构体同时保存所有候选成员会浪费空间。可在外层保存类型标识,在共用体中只保留一种有效表示:

struct operator {
    int type;
    union {
        int intNum;
        float floatNum;
        double doubleNum;
    } types;
};
struct operator op;
op.type = 0;
op.types.intNum = 352;

若共用体未命名(匿名共用体),其成员可直接作为外层结构体的成员访问:

struct operator {
    int type;
    union {
        int intNum;
        float floatNum;
        double doubleNum;
    };
};

op.type = 0;
op.intNum = 352;

命名成员与数组视图

可将具名成员与数组放在同一共用体中,以便既按名称访问又按下标遍历(布局依赖成员声明顺序与对齐):

union Coins {
    struct {
        int quarter;
        int dime;
        int nickel;
        int penny;
    };
    int coins[4];
};

union Coins change;
for (int i = 0; i < 4; i++) {
    change.coins[i] = i * 10;
}
printf("quarter=%d dime=%d nickel=%d penny=%d\n",
       change.quarter, change.dime, change.nickel, change.penny);

适用场合

  • 在多种互斥表示之间复用同一块存储以节省内存。
  • 与硬件寄存器、协议字段等“同一地址多种解释”的场景对应。
  • 配合类型字段,表示“当前有效的是哪一种成员”。

结构体便于同时保存全部成员;共用体节省空间,但须由程序逻辑保证访问的成员与当前数据含义一致。