C语言自定义类型:联合和枚举完全指南

C语言自定义类型:联合和枚举完全指南

联合(共用体)和枚举是C语言中两种重要的自定义类型。联合体所有成员共享同一块内存,而枚举用于定义一组命名的整数常量。本文将系统讲解联合体的声明、特点、大小计算,以及枚举的声明、优点和使用方法,并通过实例帮助读者灵活运用。

目录


一、联合体类型的声明

联合体(union)与结构体类似,由多个不同类型的成员组成,但所有成员共用同一块内存空间 ,因此联合体也叫共用体。编译器只为最大的成员分配足够的内存。

c 复制代码
union Un {
    char c;
    int i;
};

int main() {
    union Un u;
    printf("%zu\n", sizeof(u));  // 输出4(int占4字节)
    return 0;
}

二、联合体的特点

  • 所有成员的地址相同,即它们从同一个内存位置开始存储。
  • 修改一个成员会影响其他成员的值。

验证地址相同

c 复制代码
union Un { char c; int i; };
union Un u;
printf("%p\n", &u);    // 联合体地址
printf("%p\n", &u.c);  // 与上面相同
printf("%p\n", &u.i);  // 与上面相同

修改成员相互影响

c 复制代码
u.i = 0x11223344;
u.c = 0x55;
printf("%x\n", u.i);  // 输出0x11223355(低字节被修改)

小端 机器上,u.c 修改了 u.i 的低地址字节(即最低有效字节)。这一特性可用于判断字节序(大小端):

c 复制代码
int check_sys() {
    union { int i; char c; } u;
    u.i = 1;
    return u.c;  // 返回1为小端,0为大端
}

三、联合体大小的计算

联合体的大小至少是最大成员的大小,但需满足对齐要求总大小必须是所有成员对齐数的最大值的整数倍

c 复制代码
union Un1 {
    char c[5];  // 5字节,对齐数为1
    int i;      // 4字节,对齐数为4
};  // 最大对齐数4,总大小须为4的倍数 → 8

union Un2 {
    short c[7]; // 14字节,对齐数为2
    int i;      // 4字节,对齐数为4
};  // 最大对齐数4,总大小须为4的倍数 → 16

printf("%zu %zu\n", sizeof(union Un1), sizeof(union Un2));  // 8 16

实际应用:节省内存的礼品单设计

使用结构体时,所有属性都占用空间,造成浪费。利用联合体,不同商品共享特殊属性区域,可大幅节省内存:

c 复制代码
struct gift_list {
    int stock_number;
    double price;
    int item_type;
    union {
        struct { char title[20]; char author[20]; int num_pages; } book;
        struct { char design[30]; } mug;
        struct { char design[30]; int colors; int sizes; } shirt;
    } item;
};

四、枚举类型的声明

枚举(enum)用于将可能的值一一列举,定义一组命名的整数常量。

c 复制代码
enum Day { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
enum Sex { MALE, FEMALE, SECRET };
enum Color { RED, GREEN, BLUE };
  • 默认情况下,枚举常量从 0 开始,依次递增。
  • 可显式指定初始值:
c 复制代码
enum Color { RED = 2, GREEN = 4, BLUE = 8 };

五、枚举类型的优点

相比 #define 定义常量,枚举具有以下优势:

  1. 增强代码可读性和可维护性:含义明确的名称比数字更直观。
  2. 类型检查更严格:枚举变量只能接受枚举值(C中允许整数赋值,但C++禁止)。
  3. 便于调试 :枚举符号在调试器中可见,而 #define 宏在预处理阶段被替换,难以追踪。
  4. 一次定义多个常量 ,无需重复使用 #define
  5. 遵循作用域规则:枚举声明在函数内,则仅在该函数内有效。

六、枚举类型的使用

c 复制代码
enum Color clr = GREEN;  // 使用枚举常量赋值

// 在switch语句中非常清晰
switch (clr) {
    case RED:   printf("红色\n"); break;
    case GREEN: printf("绿色\n"); break;
    case BLUE:  printf("蓝色\n"); break;
}

在C语言中,可以将整数值赋给枚举变量(虽然不推荐),但在C++中不允许,这体现了C++更强的类型安全。


总结:联合体通过共享内存节省空间,适合存储互斥的成员;其大小需满足对齐要求。利用联合体可以巧妙实现字节序判断。枚举定义命名的整数常量,比 #define 更安全、可读、可调试,适合表示状态、选项等有限集合。掌握联合和枚举,能编写更高效、更清晰的代码。

相关推荐
-森屿安年-18 分钟前
647. 回文子串
c++·算法·动态规划
haolin123.33 分钟前
类和对象(下)
c语言·开发语言·c++
皓月斯语41 分钟前
P5736 【深基7.例2】质数筛
c++·算法·题解
极序时代GEO品牌优化2 小时前
杭州极序时代|面向地域、设备与用户画像的动态GEO
人工智能·python·算法·极序时代geo
啦啦啦啦啦zzzz2 小时前
贪心算法和动态规划
c++·算法·贪心算法·动态规划
happyprince2 小时前
篇3:bitsandbytes-深刻观-哲学与升华
人工智能·算法
应用市场3 小时前
红绿灯背后的算法:从 Webster 配时到 Max-Pressure 与强化学习
算法
木井巳3 小时前
【DFS解决floodfill算法】岛屿的最大面积
java·算法·leetcode·深度优先
(Charon)3 小时前
【C++】手写 MySQL 连接池(三):异步任务队列与工作线程
c语言·c++
m沐沐3 小时前
【机器学习】朴素贝叶斯算法:从贝叶斯定理到手写数字识别实战
人工智能·深度学习·算法·机器学习·计算机视觉·手写数字·数字识别