联合体和枚举

news2024/11/17 22:31:43

联合体:

联合体是什么?

       联合体也是一种自定义类型,这种类型定义的变量也包含一系列类型,特征是这些类型公用一块内存空间(所以叫联合体也叫公用体)可以理解为结构体公用一块内存。

//联合-联合体-共用体
//联合也是一种特殊的自定义类型,这种类型定义的变量包含一系列的成员
union Un
{
    char c;
    int i;
};
//
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;
}

       联合的成员是共用同一块内存空间的,这样一个联合变量的大小至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。联合体最好不要改动其中成员的值,因为改动一个另外也会跟着改,因为它们共用一块内存一块空间。

联合体的大小:

       联合体至少也是最大类型的整数倍。

union Un
{
    int a;//4
    char arr[5];//5  1相当于你写了5个char
    //5不是4的整数倍,对齐后是8
};//联合体大小的计算
//联合体的大小至少是成员的大小
//当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍
int main()
{
    union Un u;
    printf("%d\n", sizeof(u));
    return 0;
}

       char arr[5];相当于5个char类型,之后又追加了int,已经超过了4个字节,目前最宽字节为4,加起来一共是9字节,因为这是联合体类型,它们会共用内存。可是联合体有自己的对齐规则,如果超过了里面最大数据类型,就会对齐最大类型的的整数倍。所以这个结果是8。

       我们再来看一个例子:

union Un
{
    char a[5];
    char b[2];
}u;
int main()
{
    printf("%d\n", sizeof(u));
    return 0;
}

联合体的应用: 

       我们用联合体判断当前系统是小端存储还是大端存储。


//int check_sys()
//{
//    int a = 1;
//    return *(char*)&a;
//}
int check_sys()
{
    union
    {
        char c;
        int i;
    }u;//匿名联合体类型,用一次以后不再用
    u.i = 1;
    //返回1 小端
    //返回0 大端
    return u.c;
}
int main()
{

    //int a = 1;
    int ret = check_sys();
    //if (1 == *(char*)&a)
    //{
    //    printf("小端\n");
    //}
    //else
    //{
    //    printf("大端\n");
    //}
    if (ret == 1)
    {
        printf("小端\n");
    }
    else
    {
        printf("大端\n");
    }
    //int a = 0x11223344;
    //低地址------------->高地址
    //...[][11][22][33][44][][]...大端字节序存储模式
    //...[][44][33][22][11][][]...小端字节序存储模式
    //讨论一个数据放在内存中存放的字节顺序
    //大小端字节序问题
    return 0;
}

       我们来看另外一种用法:

union U
{
	int n;//4
	struct S
	{
		char c1;
		char c2;
		char c3;
		char c4;
	}s;//4
};

int main()
{
	//int n = 0x11223344;
	//4个字节
	//用联合体实现
	union U u = { 0 };
	u.n = 0x11223344;
	printf("%x %x %x %x\n", u.s.c1, u.s.c2, u.s.c3, u.s.c4);
	return 0;
}

 

       其实还用一种实际的用途,比如一个公司搞活动,上线一个礼品兑换单,礼品兑换单中有三种商品:图书、被子、衬衫。

       每一种商品都有:库存量、价格、商品类型和商品类型的相关信息。

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

       如果我们直接使用结构体写出一下形式:

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;//尺寸
};

        这样创建一个结构体但是一个礼品单只能兑换一个商品,只用一个商品有一些属性就会空闲着,这样势必会造成空间的浪费。此时就可以使用联合体:

struct gift_list
{
	//这是每一个商品的共同属性
	int stock_number;//库存量
	double price;//定价
	int item_type;//商品类型

	//之后就是指定一个商品
	union un 
	{
		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;
};

       此时兑换一个礼品,就开辟对应的空间,即可对空间进行合理的使用。

枚举: 

什么是枚举:

       枚举和define很像。顾名思义就是列举。因为现实生活中,总有一些东西是可以被一一列举的,比如星期,月份等。

//枚举的关键字
enum Sex
{
	//这里列举枚举enum Sex的可能取值
	MALE,
	FEMALE,
	SECRET
};

int main()
{
	printf("%d\n", MALE);
	printf("%d\n", FEMALE);
	printf("%d\n", SECRET);
	return 0;
}

       {}中的内容是枚举类型中可能取的值,也叫枚举常量。打印出出的是常数,这些可能取值都是有值的,默认从0开始,依次增加1,当然定义的时候也可以赋初值。

枚举的使用:

       我们也可以对其进行赋值:

//枚举类型
enum Sex
{
    //枚举的可能取值-常量
    MALE=9,
    FEMALE,
    SECRET
};
enum Color
{
    RED,
    GREEN=3,
    BLUE
};
int main()
{
    enum Sex s = MALE;
    enum Color c = BLUE;
    //只能拿枚举的变量来对这个变量进行赋值
    printf("%d %d %d\n", MALE, FEMALE, SECRET);
    printf("%d %d %d\n", RED, GREEN, BLUE);
    return 0;
}

       我们也可以对其逐个赋值:

//枚举的关键字
enum Sex
{
	//这里列举枚举enum Sex的可能取值
	MALE = 5,
	FEMALE = 8,
	SECRET = 10
};

int main()
{
	printf("%d\n", MALE);
	printf("%d\n", FEMALE);
	printf("%d\n", SECRET);
	return 0;
}

        枚举如果在函数中声明,就只能在函数中使用,其有生命域。 

总结:

       每个类型都有存在的意义,我们以后在生活中总会使用到它,之后我们会逐渐顿悟其具体的功能。

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

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

相关文章

基于SSM的高校共享单车管理系统的设计与实现论文

摘 要 网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。因此高校单车租赁信…

前端开发学习 (五) 生命周期函数、Ajax请求

关于vue实例的声明周期,从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期 (https://cn.vuejs.org/v2/guide/instance.html#实例生命周期 ) 而声明周期勾子就是生命周期…

我的创作纪念日(2周年)

机缘 在进入大学之前,完全没有听说过CSDN,第一次使用CSDN应该是搜C语言如何学,或者是和C语言相关的其他内容 因为我本人是学计算机专业的,大一刚开学因为疫情延迟了开学时间,老师线上教课,但是我之前是完…

[架构之路-260]:目标系统 - 设计方法 - 软件工程 - 软件设计 - 架构设计 - 基于Web的软件架构(REST与RESTful)

目录 一、基于Web的软件架构 1.1 什么是基于Web的软件架构 1.2 基于Web的软件架构的发展历史 1.3 基于Web的软件架构的优点 1.4 基于Web的软件架构的示例 1.5 基于Web的软件架构的协议标准 1.6 基于Web的软件架构 二、REST与RESTful 2.1 概述 2.2 RESTful协议 2.3 R…

自治调优!人大金仓解放DBA双手

数据库系统的性能是确保整个应用系统高效运转的关键因素,因此数据库性能调优工作至关重要。KingbaseES通过将人工调优过程内化为数据库内核,成功实现了自治调优。这种创新的调优方案为DBA提供了更高效且准确的性能调优途径,同时也显著降低了数…

【头歌系统数据库实验】实验5 SQL的多表查询-1

目录 第1关:等值连接:求S表和J表城市相同的等值连接(列顺序还是按照S、J表) 第2关:查询供应情况,并显示供应商、零件和工程三者的名称 第3关:找出上海厂商供应的所有零件号码 第4关:找出使用上海产的零…

ES 如何将国际标准时间格式进行格式化与调整时区

需求,日志收集的时候,时间格式是国际标准时间格式。形如yyyy-MM-ddTHH:mm:ss.SSS。 (2023-12-05T02:45:50.282Z)这个时区也不对,那如何将此类型的时间,进行格式化呢? 本篇文章体统一个案例&…

基于Python+Django+mysql图书管理系统

基于PythonDjangomysql图书管理系统 一、系统介绍二、功能展示三、其它系统四、获取源码 一、系统介绍 程序开发软件:Pycharm 数据库:mysql 采用技术: Django(一个MVT框架,类似Java的SSM框架) 人生苦短,我用Python&a…

Web服务安全架构——一、Web应用程序基础理论

Web安全架构 一、引言二、Web应用程序的生成过程三、程序员是如何开发Web应用程序的1、Web程序的分层结构2、各司其职的程序员3、研究 Web 应用程序的利器3.1 黑盒测试类工具3.2 白盒测试类工具 四、小结 一、引言 随着互联网的迅速发展,我们越来越多地使用Web应用…

【前端】CSS盒子模型(学习笔记)

一、盒子模型 1、网页布局的本质 先准备好相关的网页元素,网页元素基本都是盒子 Box 。利用 CSS 设置好盒子样式,然后摆放到相应位置。往盒子里面装内容. 网页布局的核心本质: 利用 CSS 摆盒子。 2、盒子模型 盒子模型:就是把 …

LangChain 25: SQL Agent通过自然语言查询数据库sqlite

LangChain系列文章 LangChain 实现给动物取名字,LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储,读取YouTube的视频文本搜索I…

随机分词与tokenizer(BPE->BBPE->Wordpiece->Unigram->sentencepiece->bytepiece)

0 tokenizer综述 根据不同的切分粒度可以把tokenizer分为: 基于词的切分,基于字的切分和基于subword的切分。 基于subword的切分是目前的主流切分方式。subword的切分包括: BPE(/BBPE), WordPiece 和 Unigram三种分词模型。其中WordPiece可以认为是一种特殊的BPE。完…

臻程密封科技(江苏)有限公司携橡胶密封产品亮相2024生物发酵展

臻程密封科技(江苏)有限公司盛装亮相2024第12届国际生物发酵产品与技术装备展(济南) 展位号:2号馆H56 臻程密封科技(江苏)有限公司专注于橡胶密封材料的研发,橡胶密封产品的生产、…

阿里云SLB的使用总结

一、什么是SLB 实现k8s的服务service的一种推荐方式,也是服务上云后,替代LVS的一个必选产品。 那么它有什么作用呢? 1、负载均衡,是它与生俱来的。可以配置多个服务器组:包括虚拟服务器组、默认服务器组、主备服务器…

来自OpenAI的官方解释:ChatGPT中的GPTs与Assistants API的区别是什么?有什么差异?

本文原文来自DataLearnerAI的官方网站: 来自OpenAI的官方解释:ChatGPT中的GPTs与Assistants API的区别是什么?有什么差异? | 数据学习者官方网站(Datalearner)https://www.datalearner.com/blog/1051701996595465 OpenAI发布的产…

大数据技术5:OLAP引擎对比分析

前言:数据仓库建设,初级的理解就是建表,将业务数据、日志数据、消息队列数据等,通过各种调度任务写入到表里供OLAP引擎使用。但要想建好数仓也是一个复杂、庞大的工程,比如要考虑:数据清洗、数据建模&#…

使用Vue3+Typescript手写一个日历签到组件

设计理念 昨天写了个简单美观的日历签到组件,使用的是Vue3TypeScript,大概逻辑是先找到本月份第一天是周几,然后开始填充月份日期:weeksArray:[[]]:之后渲染到表格中,对于签到事件触发则先判断是否是今天且还未没有签…

计算机视觉 基于Open3D了解用于网格和点云邻域分析的KD树和八叉树

一、简述 距离计算和邻域分析是理解网格和点云的形状、结构和特征的重要工具。我们这里要基于一些3D库来提取基于距离的信息并将其可视化。 与深度图或体素相比,点云和网格表示 3D 空间中的非结构化数据。点由它们的 (X, Y, Z) 坐标表示,在 3D 空间中可能彼此靠近的两…

6.3 U-boot 启动流程详解

通过对 uboot 启动流程的梳理,我们就可以掌握一些外设是在哪里被初始化的,这样当我们需要修改这些外设驱动的时候就会心里有数。 一、链接脚本 u-boot.lds 分析 uboot 的启动流程,首先要找到“入口”,找到第一行程序在哪里。程序…

【Delphi】FMX开发 ios 和 android 异同点(踩坑记)

目录 一、前言 二、补充下基础知识 1. APP程序事件:TApplicationEvent 2. APP内置Web服务器或者UDP服务端或者TCP服务端 三、iOS 和 android 平台的不同点 1. TApplicationEvent的不同点:以下不同点,请仔细阅读! 2. APP内置…