C语言----自定义类型:联合和枚举

news2025/2/26 21:04:59

 



1.联合体

联合体的特点

像结构体一样,联合体也是一个或者多个成员构成的,这些成员可以是不同的类型

联合体的关键字:union

结构体的关键字:struct

枚举的关键字:enum

但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所

以联合体也叫:共⽤体。

//struct S
//{
//    char c;
//    int i;
//
//};
//union Un
//{
//    char c;
//    int i;
//};
//int main()
//{
//    printf("%zd\n", sizeof(struct S));//8
//    printf("%zd\n", sizeof(union Un));//4
//
//    return 0;
//}
/*
但是编译器只为最⼤的成员分配⾜够的内存空间。
联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体。

联合体的特点是所有成员共⽤同⼀块内存空间,这样一个联合变量的大小,至少是最大成员的大小
(因为联合至少的有能力保存最大的那个成员)

那么为什么这里是4呢?

*/


//union Un
//{
//    char c;
//    int i;
//};
//int main()
//{
//    union Un un = { 0 };
//    printf("%zd\n", sizeof(union Un));
//    printf("%p\n", &un);//007EFDD4
把un里面的c和i的地址都打印出来
//    printf("%p\n", &(un.c));//007EFDD4
//    printf("%p\n", &(un.i));//007EFDD4
//    return 0;
//}
/*
取出的地址都是相同的
第一个字节是c,所有的4个字节都是i
所以我们发现i和c公用这4个字节的空间
所以联合体也叫共用体

我们可以发现,当我们用i的时候我们就不能用c
用c的时候就不能用i
因为改i的时候,c也改了

所以联合体成员在使用的时候,一次只能用一个成员,不能同时一起用

同一个时间只能用一个成员




对于结构体的话,c和i有各自的空间,但是对于联合体来说,成员共用空间
*/

union Un
{
    char c;
    int i;
};
int main()
{ 
    union Un un = { 0 };
    un.i = 0x11223344;
    un.c = 0x55;
    //经过调试我们不难发现随着c的改变,i也被改变了
    return 0;
}

联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体。

联合体大小的计算

联合的大小至少是最大成员的大小。

当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

//union Un
//{
//    char arr[5];//对齐数是1
//    //这个数组放在这里,跟放5个char类型是一样的
//
//    int i;//对齐数是4
//};
//int main()
//{
//    printf("%d\n", sizeof(union Un));//8
//    return 0;
//}
/*
计算出的是8,所以我们得知联合体的大小不一定是最大成员的大小
联合体的大小至少是最大成员大大小


这个联合体最大对齐数是4
那么联合体的总大小一定要是4的倍数


这个联合体最大成员的大小是这个数组,大小是5,就是相当于5个char类型

但是5不是4的倍数,所以后面还要浪费3个字节,对齐8,所以最终的大小是8个字节


所以联合体也是存在内存空间的对齐的
*/


//练习计算联合体大小
union Un
{
    short arr[7];//对齐数是1
    //这个数组放在这里,跟放5个char类型是一样的

    int i;//对齐数是4
};
int main()
{
    printf("%d\n", sizeof(union Un));//16
    return 0;
}


/*
因为shourt类型是2个字节,那么7个short就是14个字节了

short arr的对齐数是按照2来算的

i的对齐数是4,那么最大对齐数是4
那么联合体的大小必须是4的倍数


虽然说联合体很节省空间,但是也不是那么很绝对的节省空间
*/

联合体的运用

/*
图书:库存量、价格、商品类型、书名、作者、⻚数
杯⼦:商品类型、价格、库存量设计、
衬衫:设计、可选颜⾊、可选尺⼨、库存量、价格、商品类型
*/

//struct gift_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;//尺⼨
//};
//
/*
上述的结构其实设计的很简单,⽤起来也⽅便,但是结构的设计中包含了所有礼品的各种属性,这样
使得结构体的⼤⼩就会偏⼤,⽐较浪费内存。因为对于礼品兑换单中的商品来说,只有部分属性信息
是常⽤的。⽐如:
商品是图书,就不需要design、colors、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;
};

//将我们每次就只用一个的东西拎出来放到联合体里面

//我们只用开辟一块空间,就能将所有东西存进去
//每次只取一样东西
//我们这个union没有写名字,写成匿名,因为这些成员我们每次用的时候只用一次

联合体的练习

union Un
{
    char c;//第一个字节
    int i;
};
int main()
{
    union Un un = {0};
    un.i = 1;
    if (un.c == 1)
    {
        printf("小端\n");
    }
    else
    {
        printf("大端\n");
    }
    return 0;
}

2.枚举类型

枚举类型的声明

枚举顾名思义就是一一列举的意思

就是将可能的值一一列举出来

我们可以声明枚举类型

枚举的关键字是enum

//struct A
//{
//    int _a : 2;
//    int _b : 5;
//    int _c : 10;
//    int _d : 30;
//};
//int main()
//{
//    struct A sa = { 0 };
//    //scanf("%d", &sa._b);//这是错误的
//
//    //正确的⽰范
//    int b = 0;
//    scanf("%d", &b);
//    sa._b = b;//直接进行赋值
//    return 0;
//}

enum Day//星期
{
    Mon,
    Tues,
    Wed,
    Thur,
    Fri,
    Sat,
    Sun
};

enum Sex//姓名
{
    //该枚举类型的三种取值
    //都是常量,被称为枚举常量
    MALE=2,
    FEMALE=4,//我们这里是给常量一个初始值,到后面就无法进行更改了
    SECRET=8
};

int main()
{
    //我们给枚举变量赋值的都是它的可能取值
    /*enum Sex sex1 = MALE;
    enum Sex sex2 = FEMALE;*/
    printf("%d\n", MALE);//0
    printf("%d\n", FEMALE);//1
    printf("%d\n", SECRET);//2
    /*
    打印出来的值是0 1 2
    因为枚举常量的值默认是从0开始的,一次递增往下走,涨1
    */
    //如果我们希望这个值是我们期望的,我们可以在枚举类型中进行更改

    //假如我们仅仅只改变了第一个值为2
    //那么剩下两个值就是3 4


    //如果第1个值不赋值,第二个值赋值为8,那么打印出来的就是0 8 9
    //从我们设置的值进行递增,第一个值不设置的话默认就是0

    return 0;
}

枚举类型的优点

那么我们为什么使用枚举呢?

为什么使⽤枚举?

我们可以使⽤ #define 定义常量,为什么⾮要使⽤枚举?

枚举的优点:

  1. 增加代码的可读性和可维护性

  2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。

  3. 便于调试,预处理阶段会删除 #define 定义的符号

  4. 使⽤⽅便,⼀次可以定义多个常量

  5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤

enum Sex//姓名
{

    MALE=2,
    FEMALE=4,
    SECRET=8
};

int main()
{
    enum Sex sex1 = MALE;//因为MALE的类型是enum Sex类型的,所以这么进行赋值是对的
    //enum Sex sex1 = 3;这么赋值就是错的,因为3的类型是整型,但是赋值的前面的枚举类型的
    //因为类型是不一样的,所以我们不能进行赋值
    return 0;
}

define定义的话是全局的定义的

枚举类型的使用

enum Color//颜⾊
 {
   RED=1,
   GREEN=2,
   BLUE=4
 };

 enum Color clr = GREEN;//使⽤枚举常量给枚举变量赋值
//写一个计算器---完成整数的加法、减法、乘法

enum Option
{
    EXIT,//默认的值是0
    ADD=1,//值表达的是1
    SUB,
    MULL,
    DIV

};
int Add(int x, int y)
{
    return x + y;
}
int Sub(int x, int y)
{
    return x - y;
}
int Mull(int x, int y)
{
    return x * y;
}
int Div(int x, int y)
{
    return x / y;
}
void menu()//菜单
{
    printf("**********************************\n");
    printf("**********1.  add   2.  sub*******\n");
    printf("**********3.  mull  4.  div*******\n");
    printf("********* 0.    exit    **********\n");
    printf("**********************************\n");
}
int main()
{
    int input = 0,ret=0;
    int x, y;
    do
    {
        menu();
        printf("请选择一个算法");
        scanf("%d", &input);
        switch (input)
        {
        case ADD://这么写的话,ADD的值还是表达的1
            printf("请输入两个数");
            scanf("%d %d", &x, &y);
            ret=Add(x,y);
            printf("%d\n", ret);
            break;
        case SUB://对于这种我们想写什么就写什么case ADD都是可以的:
            //我们是可以不用安排这个顺序的
            printf("请输入两个数");
            scanf("%d %d", &x, &y);
            ret = Sub(x, y);
            printf("%d\n", ret);
            break;
        case MULL: 
            printf("请输入两个数");
            scanf("%d %d", &x, &y);
            ret= Mull(x, y);
            printf("%d\n", ret);

            break;
        case DIV:
            printf("请输入两个数");
            scanf("%d %d", &x, &y);
            ret = Div(x, y);
            printf("%d\n", ret);

            break;
        case 0:
            printf("退出\n");
            break;
        default:
            printf("选择错误,重新选择\n");
            break;
        }
    } while (input);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1841698.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何查看公网IP?

什么是公网IP? 公网IP(Internet Protocol)是指分配给互联网上的计算机设备的唯一标识符。公网IP地址是由互联网服务提供商(ISP)分配给用户设备,使其可以与全球范围内的其他设备进行通信。公网IP地址通常采…

Internet Download Manager(IDM6.41)软件最新版下载及详细安装教程

​根据行业数据显示支持多款浏览器,包括IE,Safari,谷歌浏览器,火狐,MSN还有opera ,通过自带的添加浏览器功能能够支持所有浏览器。实际上 一键下载所选文件:当在浏览器中用鼠标选择多个链接时&…

Spring Boot轻松整合Minio实现文件上传下载功能

一、Linux 安装Minio 安装 在/root/xxkfz/soft目录下面创建文件minio文件夹,进入minio文件夹,并创建data目录; [rootxxkfz soft]# mkdir minio [rootxxkfz soft]# cd minio [rootxxkfz minio]# mkdir data执行如下命令进行下载 [rootxxkfz…

【漏洞复现】极限OA video_file.php 任意文件读取漏洞

免责声明: 本文内容旨在提供有关特定漏洞或安全漏洞的信息,以帮助用户更好地了解可能存在的风险。公布此类信息的目的在于促进网络安全意识和技术进步,并非出于任何恶意目的。阅读者应该明白,在利用本文提到的漏洞信息或进行相关测…

在 Mac 上恢复已删除的文件夹

“嗨,我刚刚运行了重复文件查找器应用程序 Gemini 来扫描我的 Mac 以清除重复文件。它找到了很多重复的文件和文件夹,只需单击一下,它就可以帮助我删除重复的文件/文件夹。但我认为它可能会删除一些有用的重复文件。我打开垃圾箱,…

Docker环境离线安装

Docker环境离线安装 下载下列.deb包 sudo *.deb

CFD笔记

CFD 定常流动与非定常流动 定常流动:流体流动过程中各物理量均与时间无关; 非定常流动:流体流动过程中某个或某些物理量与时间有关. 运动黏度 运动粘度定义: v μ ρ v \frac{\mu}{\rho} vρμ​,其中 μ \mu μ​表示粘度…

成为前端开发负责人之前,你需要具备8个能力

自己开发前端和带领团队开发前端,基本是两码事,有些小伙伴个人能力很强,给他一个团队,他就抓瞎了,结果就变成了一人在战斗了,贝格前端工场结合多年经验,分析一下成为前端负责人要具备啥能力。 …

刷代码随想录有感(109):动态规划——01背包问题|一和零

题干&#xff1a; 代码 : class Solution { public:int findMaxForm(vector<string>& strs, int m, int n) {vector<vector<int>>dp(m 1, vector<int>(n 1, 0));dp[0][0] 0;for(string i : strs){int oneNum 0;int zeroNum 0;for(char c : i…

SolidWorks软件天津代理商:官方授权亿达四方,企业的信赖之选

在快速发展的制造业领域&#xff0c;设计与创新是推动企业持续前进的核心动力。作为世界领先的三维机械设计解决方案&#xff0c;SolidWorks以其强大的功能、直观的操作界面以及高效的协作能力&#xff0c;成为众多天津企业加速产品开发周期、提升市场竞争力的首选工具。而在天…

C语言 | Leetcode C语言题解之第160题相交链表

题目&#xff1a; 题解&#xff1a; struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {if (headA NULL || headB NULL) {return NULL;}struct ListNode *pA headA, *pB headB;while (pA ! pB) {pA pA NULL ? headB : pA->ne…

交易盈利秘诀分享

在交易的过程中&#xff0c;大多数投资者容易被每天纷繁变化的行情所迷惑&#xff0c;看不清交易的本质&#xff0c;他们每天追求确定性&#xff0c;追求暴利&#xff0c;追求传说中的圣杯&#xff0c;然后&#xff0c;迷失在交易利益的得失之中&#xff0c;无法悟透交易的准则…

为微信小程序项目添加eslint

背景 在使用vscode开发微信小程序的过程中&#xff0c;修改js的时候发现没有报错提示&#xff0c;让我很不习惯&#xff0c;所以想为微信小程序项目添加eslint配置 编码实战 为微信小程序配置ESLint可以遵循以下步骤&#xff1a; 安装ESLint及其相关插件 首先&#xff0c;…

F611V36 SOT23-6 4.2V 气压检测和充放电三合一咪头专用芯片-昱灿

F911 是一款咪头专用芯片&#xff0c;集成涓流、恒流、恒压三段式充电管理&#xff0c;符合锂电池充电规范。充电输入可直接从USB口取电&#xff0c;充电电流默认530mA。 集成 50mΩ 的放电 MOS 开关&#xff0c;无需外部MOS&#xff0c;大大降低BOM成本。内置MOS导通PWM控制&a…

Hydra常用爆破命令

常用破解命令 SSH 破解 hydra -l 用户名 -p 密码字典 -t 线程 -vV -e ns ip ssh hydra -l 用户名 -p 密码字典 -t 线程 -o save.log -vV ip sshFTP 破解 hydra ftp://ip -l 用户名 -P 密码字典 -t 线程(默认16) -vV hydra ftp://ip -l 用户名 -P 密码字典 -e ns -vVWeb 登陆…

Linux根目录挂载点(/dev/mapper/centos-root)扩容

如果我们在安装系统是采用自定义分区的话&#xff0c;就可以提前规划好这个事情。但是如果平常没注意就直接采用默认安装的方式的话。一旦 根目录的容量耗尽&#xff0c;将会影响业务的运行。今天我们来扩容逻辑卷。 默认安装的话会给home目录分比较多的空间&#xff0c;我们可…

闲置资源共享平台

摘 要 随着共享经济的高速发展以及人们对物品的需求方面也越来也丰富&#xff0c;而且各大高校的大学生们的购买力也越来越强&#xff0c;随之而来的问题就是身边的闲置资源也越来越多&#xff0c;但是也有许多的大学生对物品的要求方面不是很高&#xff0c;也愿意买下经济实惠…

kimi+的+能为论文写作+出什么?我帮你试过了!

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 Kimi是月之暗面科技有限公司开发的个性化智能助手功能。相比kimi&#xff0c;Kimi能够提供个性化定制服务&#xff0c;根据用户特定需求提供更专业深入的辅助&#xff0c;实现一对一的智…

国内出版社数字化资源的现状与挑战:一场未充分利用的数字转型

**概述&#xff1a;**在当前数字化高速发展的时代背景下&#xff0c;国内教育出版社在数字化资源的开发与应用上面临着诸多挑战和不足。本文将针对读者提出的问题和反馈&#xff0c;探讨国内教育出版社数字化资源存在的问题&#xff0c;并分析可能的原因和改进方向。 **正文&a…

数据资产:打破数据孤岛,实现数据互联互通,构建企业智能化转型的重要桥梁。通过高效整合与利用数据资源,推动企业决策的科学化、精准化,助力企业迈向智能化新时代

目录 一、引言 二、数据孤岛现象及其影响 三、打破数据孤岛&#xff0c;实现数据互联互通 1、制定统一的数据标准和管理规范 2、建设统一的数据平台 3、推广数据共享和开放文化 四、数据资产在智能化转型中的重要作用 1、推动企业决策的科学化、精准化 2、优化企业运营…