【C语言】位段枚举联合

news2024/9/25 7:18:59

鹅,鹅,鹅,曲项向天歌。白毛浮绿水,红掌拨清波。 — 唐代·骆宾王《咏鹅》

在这里插入图片描述


    这篇博客我们会详细介绍位段,以及枚举类型和联合类型
    在这里插入图片描述

    位段是什么?🍀

    位段的声明和结构是类似的,有两个不同:
    1.位段的成员必须是 int、unsigned int 或signed int 以及 char或unsigned char。
    2.位段的成员名后边有一个冒号和一个数字

    struct A
    {
     int _a:2; //a这个成员只占2个bit位  
     int _b:5; //b这个成员只占5个bit位
     int _c:10;
     int _d:30;
    };
    

    这个A就是一个位段类型 。
    但是我们要根据需求来决定:后分配几个比特位比如下面的情况:

    int _a:2;
    //_a这个成员只占2个bit位 
    只有两个比特位的取值就是下面
    //00-0
    //01-1
    //10-2
    //11-3
    只可能表达0~34个值没有其他值
    

    有些时候不需要那么大一个int 所以才用位段。

    位段的内存分配🐽

    1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
    2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
    3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。(我们讲的是VS的)
    struct A
    {
    	int _a : 2;//_a这个成员只占2个bit位
    	int _b : 5;//_b这个成员只占5个bit位
    	int _c : 10;
    	int _d : 30;
    };//8
    
    int main()
    {
    	printf("%d\n", sizeof(struct A));
    
    	return 0;
    }
    
    1. int 在32位下是32bit, _a占2 _b占5 _c占10 还剩下15。
    2. 这15个比特位就直接给_d使用吗?这个要取决于编译器,还剩15个d肯定是不够的。
    3. 我们肯定要开辟另外4个字节,那么问题来了,还剩的这15个我们用不用?反正VS不用。
      接下来我们更仔细的研究一下
    struct S
    {
    	char a : 3;
    	char b : 4;
    	char c : 5;
    	char d : 4;
    };
    
    int main()
    {
    	struct S s = { 0 };
    	printf("%d\n", sizeof(s));
    
    	s.a = 10;
    	s.b = 12;
    	s.c = 3;
    	s.d = 4;
    
    	return 0;
    }
    

    在这里插入图片描述
    这就是在内存的排列方式。

    位段的跨平台问题

    1. int 位段被当成有符号数还是无符号数是不确定的。
    2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机
      器会出问题。
    3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
    4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是
      舍弃剩余的位还是利用,这是不确定的。

    枚举✳️

    枚举顾名思义就是一一列举。 把可能的取值一一列举。 比如我们现实生活中:
    一周的星期一到星期日是有限的7天,可以一一列举
    性别有:男、女、保密,也可以一一列举。
    月份有12个月,也可以一一列举
    这里就可以使用枚举了。

    enum Day//星期
    {
     Mon,
     Tues,
     Wed,
     Thur,
     Fri,
     Sat,
     Sun
    };
    enum Sex//性别
    {
     MALE,
     FEMALE,
     SECRET
    }enum Color//颜色
    {
     RED,
     GREEN,
     BLUE
    };
    

    以上定义的 enum Day , enum Sex , enum Color 都是枚举类型。
    {}中的内容是枚举类型的可能取值,也叫 枚举常量 。
    这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。

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

    枚举的优点 🦑

    为什么使用枚举?
    我们可以使用 #define 定义常量,为什么非要使用枚举?
    枚举的优点:

    1. 增加代码的可读性和可维护性 (类似Switch的case 1 改成 case Add)
    2. 和#define定义的标识符比较枚举有类型检查,更加严谨。(C语言检查不够严格,cpp更严格)enum Color c = 5; 5 是int类型 c 是enum color类型
    3. 防止了命名污染(封装)限制了使用范围,而#define全局使用
    4. 便于调试调试发生在.exe,而enum在调试的时候跟我们看到的是一样的,而#define不一样变成了#define定义的值
    5. 使用方便,一次可以定义多个常量 (#define太麻烦而且一次只能定义一个)

    枚举的使用

    enum Color//颜色
    {
     RED=1,
     GREEN=2,
     BLUE=4
    };
    enum Color clr = GREEN;
    //只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。
    clr = 5;               上面已经讲过了,
    

    联合体(共用体)🐣

    联合也是一种特殊的自定义类型
    这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。

    比如:

    union Un
    {
    	char c;//1
    	int i;//4
    };
    
    int main()
    {
    	union Un u;
    	
    	printf("%d", sizeof(u));
    
    	return 0;
    }
    

    那么这个联合体大小为多少呢?
    在这里插入图片描述
    为什么?,我们来探究。

    union Un
    {
    	char c;//1
    	int i;//4
    };
    int main()
    {
    	union Un u;
    	printf("%d\n", sizeof(u));
    	printf("%p\n", &u);
    	printf("%p\n", &(u.c));
    	printf("%p\n", &(u.i));
    	return 0;
    }
    

    我们尝试打印一下联合体的地址,以及c变量,i变量的地址。
    在这里插入图片描述
    发现居然都是一样的!
    在这里插入图片描述
    我们画图简单的表述一下就知道了,这就是共用的意义。那么我们可以合理的想象,如果c变量中放了一个值,如果再在i变量中放一个值是不是就会把c变量的值改变呢?或者反过来也是一样呢?
    在介绍一个问题之前我们先介绍一下联合体的原则:
    联合的成员是共用同一块内存空间的这样一个联合变量的大小,至少是最大成员的大小(因为联 合至少得有能力保存最大的那个成员)。

    联合的特点

    //下面输出的结果是什么?
    un.i = 0x11223344;
    un.c = 0x55;
    printf("%x\n", un.i);
    

    在这里插入图片描述
    这就是跟小端有关系了。
    在这里插入图片描述

    联合大小的计算 💥

    ● 联合的大小至少是最大成员的大小。
    ● 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
    比如:

     union Un1
    {
     char c[5];//1
     int i;//4
    
    
      //0      char   
      //1      char
      //2      char
      //3      char
      //4      char
    
       共用前4个字节   int
       一共是5个字节再对齐到8    
        
    };
    

    在这里插入图片描述

    union Un2
    {
        short c[7];
        int i;//公用前4个字节
    };
    //  c:2-15 
    //  i:2-5
    //下面输出的结果是什么?
    int main()
    {
        printf("%d\n", sizeof(union Un2));
        return 0;
    }
    

    在这里插入图片描述

    总结😈

    这篇博客是用来梳理位段枚举联合的相关知识的,能让我们很好的了解位段枚举联合的特性和运用,让我们的C语言功底更上一层楼 完(๑′ᴗ‵๑)
    在这里插入图片描述在这里插入图片描述

    在这里插入图片描述

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

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

    相关文章

    数据库数据恢复-导致oracle数据库数据丢失的常见故障分析

    作为存储和处理数据的系统,oracle数据库在使用过程中不可避免会出现各种导致数据丢失和数据损坏的故障。北亚企安数据恢复工程师根据十多年的案例经验,总结出oracle数据库常见故障以及恢复可能性。 1、Oracle数据库无法启动或者启动后无法正常工作。 如果…

    如何写一篇吸引人的美食营销软文?纯干货

    信息化时代,美食营销软文已经成为了餐饮业吸引顾客的重要手段之一。那么,如何才能写出一篇吸引人的美食营销软文呢?本文伯乐网络传媒将从以下几个方面进行深刻讨论。 一、抓住顾客的心理需求 要写一篇成功的美食营销软文,首先要抓…

    最新版Onenet云平台HTTP协议接入上传数据

    2023年最新版Onenet更新后,原来的多协议接口已经找不到,由于需要用HTTP接入,就研究了一下新版Onenet云平台,搞清楚Onenet云平台的鉴权信息,就知道怎么上传数据了,包括后续上传实际数据,其实只需…

    Jenkins 还可以支持钉钉消息通知?一个插件带你搞定!

    Jenkins 作为最流行的开源持续集成平台,其强大的拓展功能一直备受测试人员及开发人员的青睐。大家都知道我们可以在 Jenkins 中安装 Email 插件支持构建之后通过邮件将结果及时通知到相关人员。 但其实 Jenkins 还可以支持钉钉消息通知,其主要通过 Ding…

    800*A. Cherry

    Example input 4 3 2 4 3 4 3 2 3 1 2 69 69 6 719313 273225 402638 473783 804745 323328output 12 6 4761 381274500335解析: 每次只计算相邻两个数的乘积,乘积的最大值即为答案。 取三个元素 a,b,c,那么其最大值…

    Vue3 Radio单选切换展示不同内容

    Vue3 Radio单选框切换展示不同内容 环境&#xff1a;vue3tsviteelement plus 技巧&#xff1a;v-if&#xff0c;v-show的使用 实现功能&#xff1a;点击单选框展示不同的输入框 效果实现前的代码&#xff1a; <template><div class"home"><el-row …

    HuntingNFT 全新玩法引爆市场,GameFi掘金新热土?

    “HuntingNFT v2 版本推出后&#xff0c;全新上线的驻守玩法、献祭玩法正在为玩家带来十分可观且持续的收益&#xff0c;其正在成为 GameFi 掘金的新热土。” 在经历了 2021 年的短暂狂欢后&#xff0c;随着 2022 年年初市场遇冷转熊&#xff0c;GameFi 市场也开始不断降温。根…

    IDEA live templates

    surround 在SQL的xml里 可以修改变量 官方文档 CDATA not null <if test"$SELECTION$ ! null and $SELECTION$ ! "> and $VAR1$ #{$SELECTION$} </if>not null like mysql <if test"$SELECTION$ ! null and $SELECTION$ ! "> and…

    Gitlab 备份与恢复

    备份 1、备份数据&#xff08;手动备份&#xff09; gitlab-rake gitlab:backup:create2、备份数据&#xff08;定时任务备份&#xff09; [rootlocalhost ]# crontab -l 00 1 * * * /opt/gitlab/bin/gitlab-rake gitlab:backup:create 说明&#xff1a;每天凌晨1点备份数据…

    WebDAV之π-Disk派盘 + POJO

    POJO 支持WebDAV方式连接π-Disk派盘。 Pojo文档管理是一种简单而强大的文档管理方法,利用Java编程语言的普通对象来管理文档。你可以使用Pojo对象来表示和操作文档的属性、内容和元数据。这种面向对象的方法使得文档管理更加灵活和可扩展。 结合派盘,Pojo文档管理变得更加…

    按是否手工执行测试的角度划分:手工测试、自动化测试

    1.手工测试&#xff08;Manual testing&#xff09; 手工测试是由人一个一个的输入用例&#xff0c;然后观察结果&#xff0c;和机器测试相对应&#xff0c;属于比较原始但是必须的一个步骤。 由专门的测试人员从用户视角来验证软件是否满足设计要求的行为。 更适用针对深度…

    炎热夏天,VR全景让你宅家也能逛风景

    夏天的快乐都是空调给的&#xff0c;进入三伏天气以来&#xff0c;连续的高温让人坐着都是一身汗&#xff0c;尤其是活泼好动的小朋友们&#xff0c;不出去玩那是不可能的。不妨改变下策略&#xff0c;让小朋友们转战线上&#xff0c;还能学习知识&#xff0c;是不是美滋滋呢~~…

    JS逆向之猿人学爬虫第20题-wasm

    文章目录 题目地址sign参数分析python算法还原往期逆向文章推荐题目地址 https://match.yuanrenxue.cn/match/20第20题被置顶到了第1页,题目难度 写的是中等 算法很简单,就一个标准的md5算法,主要是盐值不确定, 而盐值就在wasm里面,可以说难点就在于wasm分析 sign参数分…

    history命令:显示命令执行时间

    1.修改配置文件 vim /etc/profile 添加内容 export HISTTIMEFORMAT"%Y-%m-%d %H:%M:%S " ​ #注意&#xff1a;在末尾的“引号”与“S”之间&#xff0c;加入一位空格&#xff0c;将日期时间和历史命令用空格相隔开来。 你也可以换一种清晰的形式&#xff0c;效果…

    java线程中的常见方法(详解)

    方法简介 方法名 功能 说明 start() 启动一个新线程&#xff0c;在新的线程运行 run 方法中的代码 start 方法只是让线程进入就绪&#xff0c;里面代码不一定立刻运行&#xff08;CPU 的时间片还没分给它&#xff09;。每个线程对象的start方法只能调用一次&#xff0c;如…

    程序员必读十大电子书

    程序员必读十大电子书 云原生架构白皮书 2022 版程序员面试宝典Java 工程师成神之路微服务治理技术白皮书Java 开发手册&#xff08;嵩山版&#xff09;必致&#xff08;BizDevOps&#xff09;白皮书 2022Elasticsearch 全观测技术解析与应用&#xff08;构建日志、指标、APM 统…

    Tik Tok海外公会是什么?

    在数字社交媒体领域&#xff0c;TikTok已成为全球性的热门应用之一&#xff0c;印尼市场也不例外。作为全球第四人口最多的国家&#xff0c;印尼的年轻人口众多&#xff0c;是一个极具潜力的市场。对于希望在印尼市场进行TikTok公会申请的机构来说&#xff0c;了解市场发展趋势…

    NLP实验案例100个(1-5)

    实验一 array数组&#xff08;01&#xff09; 一、实验目的及要求 1.安装numpy环境&#xff0c;掌握基本的数组知识以及操作。 二、实验设备&#xff08;环境&#xff09;及要求 开发环境&#xff1a;jupyter notebook 开发语言以及相关的库&#xff1a;python开发语言、nu…

    微信小程序:授权登录获取手机号及获取基本信息等

    1、授权获取code&#xff0c;换取open_id wx.login({success(res) {console.log(res.code)if (res.code) {//调自己后台接口换取open_id}} })微信文档 2、获取手机号 1&#xff09;需要将 button 组件 open-type 的值设置为 getPhoneNumber&#xff0c;当用户点击并同意之后…

    大采购3.0,打造企业采购数智化的韧性变革!

    大采购3.0&#xff0c;深化采购全链路管控&#xff0c;聚焦数智化运营、智慧化监管、个性化需求适配、一体化协同、稳定可靠、安全可信、企业级服务七大核心基因&#xff0c;围绕采购管理、供应商全生命周期管理、人工智能深入应用、易用性、交付能力等方面进行了全面升级和优化…