【C语言】自定义类型:联合与枚举的简明概述

简介: 【C语言】自定义类型:联合与枚举的简明概述

一、联合体(Union)

1.1 联合体的声明

联合体是一个或多个成员组成,其中成员可以是不同类型,并且所有成员共用同一块内存空间,所以联合体也称为共用体。联合体声明的关键字是union。

//联合体类型的声明
union Un
{
    char c;
    int i;
};
int main()
{
    union Un un;//联合体的定义
    sizeof("%d\n,sizeof(un)");-->4
    return 0;
}

1.2 联合体的特点

联合体的特点:

  • 联合体所有成员共用同一块内存空间,一个联合体变量的大小,至少是最大成员的大小,编译器只为最大的成员分配足够大的空间
  • 给联合体其中一个成员赋值,其他成员的值也会变化
代码一
union Un
{
    char c;
    int i;
};
int main()
{
    union Un un = {0};
    // 下⾯输出的结果是⼀样的吗?
    printf("%p\n", &(un.i));
    printf("%p\n", &(un.c));
    printf("%p\n", &un);
    return 0;
}
结果:001AF85C
    001AF85C
    001AF85C
代码二
union Un
{
    char c;
    int i;
};
int main()
{
    union Un un = {0};
    un.i = 0x11223344;
    un.c = 0x55;
    printf("%x\n", un.i);
    return 0;
}
结果:11223355

说明】:

从代码一输出的结果是相同的,说明联合体中成员变量是一块空间存储。从代码二输出中,第四个字节的内容被修改位55,对联合体中成员赋值,会影响联合体的全部成员,char类型只占用一个字节。

1.3 结构体和联合体内存布局对比

struct Su
{
    char c;
    int i;
}S;
Union Un
{
    char c;
    int i;
}un;

说明】:结构体是通过以为空间换取时间设计("浪费"空间),而联合体是节省空间


1.4 计算联合体的大小

规则如下】:

  • 联合体的大小至少是最大成员的大小
  • 当最大成员大小(联合体总大小)要对齐到最大对齐数的整数倍
#include <stdio.h>
union Un1
{
    char c[5]; 1 8 1//最大成员大小为5
        int i;  4 8 4
};//最大对齐数位4,最大成员大小为5,对齐到8是最大对齐数的整数倍
union Un2
{
    short c[7]; 2 8 2//最大成员大小为7
        int i;  4 8 4
};//最大对齐数位4,最大成员大小为7,对齐到16是最大对齐数的整数倍
int main()
{
    printf("%d\n", sizeof(union Un1));-->8
    printf("%d\n", sizeof(union Un2));-->16
    return 0;
}

1.5 联合体的实际使用样例

场景如下,搞一个礼品兑换,礼品兑换单中有三种商品:图书、被子、衬衫。每一种商品的信息:库存量、价格等相关的其他信息

  • 图书:书名、作者、页数
  • 杯子:设计
  • 衬衫:设计、可选颜色、尺寸

如果单纯采用结构体,将变量全部写下来:

struct list
{
    int stock_number;//库存量
    double price;//定价
    int item_type;//商品类型
    char title[20];//书名
    char author[20];//作者
    int num_pages;//页数
    char design[30]//设计
        int colors;//颜色
    int sizes;//尺寸   
}

优点】:

  • 设计简单,使用方便

【缺点】:

  • 包含了各种的属性,内存占用比较大、浪费空间也加大了
  • 部分属性信息是常用的,有些商品不需这部分信息

解决办法:】把公共属性单独写出来,剩余属于各种商品本身的属性使用联合体处理,再一定程度上节省了内存

配合上联合体设计:

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;
};

说明】:

将不同商品的本身属性使用联合体处理,初始化的时候是初始化一个联合体对象,联合体里面只支持初始化一个结构体成员,没法加中括号,再在中括号里面分别初始化,语法不允许

而且这种情况我们正常使用时本身就只会选择一个成员进行初始化。如果需要初始化多个对象,则将其放进一个结构体数组初始化,每个数组元素都是结构体单独初始化

联合体习题】:判断当前机器是大端还是小端(通过数字和地址关系)

int check_sys()
{
    union
    {
    int i;
        char c;
    }
    un.i=1;//00 00 00 01-->01 00 00 00(小端)
    return un.c 
}

二、Enum(枚举)

枚举顾名思义就是⼀>列举

列举可能的取值:用于定义一组具有离散值的常量,使数据更简洁、方便使用,关枚举的关键字enum。

2.1 枚举类型的声明

比如列举:星期一到星期日十有限的七天或者性别、颜色等。

enum Day
{
    Mon,
    Tues,
    Wed,
    Thur,
    Fri,
    Sat,
    Sun
};
enum Sex
{
    Man;
    Woman;
}

以上定义的enum Day、enum Sex都是枚举类型,而{}中枚举类型的可能取值称为枚举常量

在声明枚举类型的时候,可以同时对枚举常量初始化(枚举常量都是有值的,默认从0开始,并且依次递增)

enum Sex
{
    Man=10;
    Woman;//11
}

2.2 枚举类型的优点

问题】:

这里就像#define定义常量,为什么还有枚举这样子数据类型

枚举的优点】:

  1. 增加代码的可读性和可维护性
  2. 枚举类型有类型检查,更加严谨
  3. 便于调试,预处理阶段会删除#define定义的符号
  4. 一次可以定义多个枚举常量,使用方便
  5. 枚举常量是遵循作用域规则的,枚举声明在函数内,只能在函数内使用

2.3 枚举类型的使用

enum Color
{
  Red=2;
    Blue=1;
}
enum Color clr=Blue;

使用枚举常量给枚举变量赋值,也可以拿整数给枚举变量赋值(C语言可以,C++不行,C++检查比较严格)

使用场景】:

比如:在枚举类型中定义事物的编号,通过输入数字(编号),找到对应的事情

enum color
{
    Red=1;
    Blue;//1递增为2
}
int main()
{ 
    enum color favorite_color;
    printf("请输入你喜欢的颜色:(1.Red,2.Bule)");
    //输入1或2去代表Red或Bule
    scanf("%u",&favorite_color);
    switch(favorite_color)
    {
        case Red(Red==1):
            printf("%你喜欢的颜色为红色");
            break;
        case Blue(Blue==2):
            printf("%你喜欢的颜色为蓝色");
            break;
        default :
            printf("没有喜欢的颜色")
    } 
}

【说明】:这里不是输入枚举对象,而是枚举对象对应的数字。



相关文章
|
2月前
|
安全 编译器 Linux
【c语言】轻松拿捏自定义类型
本文介绍了C语言中的三种自定义类型:结构体、联合体和枚举类型。结构体可以包含多个不同类型的成员,支持自引用和内存对齐。联合体的所有成员共享同一块内存,适用于判断机器的大小端。枚举类型用于列举固定值,增加代码的可读性和安全性。文中详细讲解了每种类型的声明、特点和使用方法,并提供了示例代码。
26 3
|
2月前
|
存储 编译器 C语言
c语言回顾-联合和枚举
c语言回顾-联合和枚举
33 4
|
2月前
|
存储 C语言 C++
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
|
2月前
|
存储 编译器 Linux
C语言——自定义类型
C语言——自定义类型
|
2月前
|
存储 安全 编译器
深入理解C语言中的枚举
深入理解C语言中的枚举
|
4月前
|
存储 编译器 C语言
【C语言篇】自定义类型:联合体和枚举详细介绍
像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
46 1
|
4月前
|
存储 安全 编译器
C语言自定义类型
C语言自定义类型
34 10
|
4月前
|
C语言
C语言中的math库概述
C语言中的math库概述
111 1
|
6月前
|
C语言
枚举(C语言)
枚举(C语言)
|
6月前
|
编译器 C语言
C语言枚举:深入探索下标默认值、自定义值及部分自定义情况
C语言枚举:深入探索下标默认值、自定义值及部分自定义情况