C语言之我对结构体与联合体的认识

news2024/11/15 15:40:32

9efbcbc3d25747719da38c01b3fa9b4f.gif

 c语言中的小小白-CSDN博客c语言中的小小白关注算法,c++,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm=1001.2014.3001.5343

给大家分享一句我很喜欢我话:

知不足而奋进,望远山而前行!!!

铁铁们,成功的路上必然是孤独且艰难的,但是我们不可以放弃,远山就在前方,但我们能力仍然不足,所有我们更要奋进前行!!!

今天我们更新了联合体和结构体的内容,

🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

一、结构体位段

我们先来说一下上一篇结构体博客中遗留下来的问题吧,叫做结构体位段问题,这个问题该咋去讲呢,就是结构体位段。

下面我们来看一串代码:

//结构体位段
//节省空间内存。
struct S
{
	int _a:2;//只占2个bit位
	int _b:5;//只占5个bit位
	int _c:10;//   10个
	int _d:30;//   30个 
};

我们前面讲了结构体内存对齐,我们说了他的作用是通过耗费更多的空间来获取更快的运行速度,然后这个结构体位段的作用是什么呢,它就是要耗费更少的内存空间。

我们其中的数字不是指的字节,而是bit位,我们知道,一个int类型的数占四个字节,那么我们只用两个bit位能存储这个数嘛,下面我们来试试看:

我们知道2的二进制是:00000010,然后我们知道一个其中的一个数占一个bit位,因此如果储存一个2的话只需要两个bit位也是可以实现的,所以这个就可以节省许多内存。

位段的跨平台问题:

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

总结:

跟结构相比,位段可以达到较好的效果,并且可以很好的节省空间,但是就是存在跨平台的问题。

二、结构体内存的分配

先看一串代码:

struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;

};
 
int main()
{
	struct S s = { 0 };
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;

	return 0;
}

大家认为位段是如何开辟内存空间的呢?下面我们来看一下。

在位段内存分配时,我们的规则大概是这样的,就是我们先会开辟一段内存,一个字节,八个bit位,开辟好之后,我们是从左往右存呢,还是从右往左存呢,答案就是从右往左存,

大概就是这样,然后我们看第一个字节处,我们先用了三个bit位,然后又占了四个,但是还会剩下一个,但是这一个已经不够下一个继续使用了,因此会丢弃掉这一个,继续开辟一块新的字节。

三、联合和枚举:

3.1联合体

像结构体一样,由一个或者多个成员构成,这些成员可以不同的类型。

下面我们通过一串代码来了解一下联合体

union Un
{
	char c;
	int i;
};

int main()
{
	union Un u = { 0 };
	printf("%zd\n", sizeof(u));
	return 0;
}

大家认为这串代码会输出什么呢?char占一个字节,然后int占四个字节,按对齐的规则是不是占八个字节呢,我们运行一下看一下:

我们发现结果是4,这是为什么呢?

这就和联合体的定义有关系了,其实char定义的这个数和int类型定义的数存放在一个地址处,我们用一串代码来验证一下:

union Un
{
	char c;
	int i;
};

int main()
{
	union Un u = { 0 };
	printf("%zd\n", sizeof(u));

	printf("%p\n", &u);
	printf("%p\n", &(u.c));
	printf("%p\n", &(u.i));

	return 0;
}

我们可以发现这串代码打印的这两个地址是相同的,因此我们就可以验证出他就是存放相同地址处。

这里还有一个知识点,联合体的大小至少是最大成员的大小,当最大成员的大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。

下面我们再来做一个练习:

union Un
{
	short s[7];
	int i;
};

int main()
{
	union Un u = { 0 };
	printf("%zd\n", sizeof(u));
	return 0;
}

大家认为这个代码会输出什么呢,一个short类型占两个字节,然后七个就是十四个字节,但是int是4,又要求输出的是最大对齐数的整数倍,所以16才符合最终的结果。答案就是16.

3.1.1联合体有什么用呢?

使用联合体是可以节省空间的,举例:
比如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。
每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。
图书:书名、作者、⻚数
杯子:设计
衬衫:设计、可选颜色、可选尺寸
那我们不耐心思考,直接写出⼀下结构:
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;
};

这样来看我们是不是就节省了许多的空间呢。

我们下面再通过联合体判断一下机器是大端还是小端。

int check_sys()
{
	union Un
	{
		char c;
		int i;
	}u;
	u.i = 1;
	return u.c;
}

int main()
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else 
		printf("大端\n");

	return 0;
}

这个代码是不是太妙了呢,直接拿出四个字节中的一个字节,直接就可以判断出来了。

总结:

这次我们介绍了关于结构体位段、联合和枚举还有联合体的内容。希望大家可以从中学到东西。

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

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

相关文章

APP广告变现初期,广告测试怎么做?

广告变现能给应用带来收入增长的一条非常有效的途径,同时可以帮助变现困难的产品类型最快实现盈利,例如付费下载、工具类产品等。 广告测试是APP广告变现中必不可少的一步,广告测试可以用来验证增减广告位会不会引起用户反感、对接广告平台能…

如何解决MySQL死锁(看懂MySQL锁日志)

有时候系统在生产运行着,会突然爆出 [40001][1213] Deadlock found when trying to get lock; try restarting transaction 这个时候每个人都会很紧张,因为死锁会影响DB性能,严重时甚至拖垮整个系统。在实际的环境中,很多服务会共…

JMeter压测SpringBoot项目

压力测试架构图如下: 配置JMeter 在JMeter的bin目录,双击jmeter.bat 新建一个测试计划,并右键添加线程组: 进行配置 一共会发生4万次请求。 ctrl + s保存; 添加http请求: 配置http请求: 配置断言,来判断当前请求是否成功: 正常响应如下:

EtherCAT开源主站 IGH 介绍及主站伺服控制过程

目录 前言 IGH EtherCAT主站介绍 主要特点和功能 使用场景 SOEM 主站介绍 SOEM 的特点和功能 SOEM 的使用场景 IGH 主站 和 SOEM对比 1. 功能和复杂性 2. 资源消耗和移植性 3. 使用场景 EtherCAT 通信原理 EtherCAT主站控制伺服过程 位置规划模式 原点复归模式…

金融知识分享系列之:ATR指标

金融知识分享系列之:ATR指标 一、ATR指标二、指标原理三、海龟交易法应用1.计算开仓数量2.制定止损/加仓规则 四、ATR指标总结 一、ATR指标 利用ATR指标计算仓位,设置止损的规则名称:平均真实波动幅度参数:(默认14)组成&#xff…

CMeet系列技术生态沙龙---《探索未来:生成式AI赋能千行百业·杭州》

当前数字化浪潮下,生成式AI技术正成为推动产业升级、提升竞争力的关键力量。为深入探索未来AI技术的赋能作用,促进技术生态的繁荣与发展,CSDN-CMeet系列沙龙活动旨在搭建一个交流与探索的平台,通过分享前沿研究成果和应用案例&…

OpenCV实现OCR图片文本检测

一、操作步骤 把左边这样的图片,通过仿射变换转换成右边那样的图片。 然后再通过pytesseract读取图片内容得到图片中的文本就好了。 需要使用到: 仿射变换ocr识别 注:本文使用现成图片,轮廓检测较为明显,若是自己拍…

Css 样式记录

实现两栏布局如图所示样式&#xff1a; 方法1&#xff1a; <div style"display: flex; justify-content: space-between; width:100%;"> <div>1</div> <div>2</div> </div> 方法2&#xff1a; <div style"display: fle…

pytest ui自动化

chromedriver.exe 要对应已安装的chrome版本号

大数据面试题 —— Zookeeper

目录 ZooKeeper 的定义ZooKeeper 的特点ZooKeeper 的应用场景你觉得Zookeeper比较重要的功能ZooKeeper 的选举机制 ***zookeeper主节点故障&#xff0c;如何重新选举&#xff1f;ZooKeeper 的监听原理 ***zookeeper集群的节点数为什么建议奇数台 ***ZooKeeper 的部署方式有哪几…

C语言种sizeof()和strlen的区别

sizeof 是 C 语言内置的操作符关键字&#xff0c;而 strlen 是 C 语言库函数&#xff1b; sizeof 仅用于计算数据类型的大小或者变量的大小&#xff0c;而 strlen 只能以结尾为 \0 的字符串作为参数&#xff1b; 编译器在编译时就计算出了 sizeof 的结果&#xff0c;而 strlen …

02_设计模式

文章目录 设计模式设计模式分类UML类图设计模式的原则 常用设计模式创建型设计模式单例设计模式饿汉模式懒汉模式&#xff08;线程不安全&#xff09;懒汉模式&#xff08;线程安全&#xff09;- Synchronized懒汉模式&#xff08;线程安全&#xff09;- Double Check懒汉模式&…

Android 系统源码快速入门

Android源码快速入门 今天分享的内容是Android源码快速入门&#xff0c;主要分为以下几个步骤&#xff1a; * 硬件要求 * 虚拟机安装 * 开发环境搭建 * 下载编译源码 * 从一个简单的实际开发需求体验 Framework 开发硬件要求 用于 Android Framework 开发的电脑需要较强的 C…

算法沉淀——贪心算法二(leetcode真题剖析)

算法沉淀——贪心算法二 01.最长递增子序列02.递增的三元子序列03.最长连续递增序列04.买卖股票的最佳时机 01.最长递增子序列 题目链接&#xff1a;https://leetcode.cn/problems/longest-increasing-subsequence/ 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子…

【第十一章】改进神经网络学习方式-Softmax

我们将主要使用交叉熵成本来解决学习减速的问题。然而&#xff0c;我想简要描述另一种解决方法&#xff0c;基于所谓的 softmax 层神经元。在本章的剩余部分&#xff0c;我们实际上不会使用 softmax 层&#xff0c;因此如果你时间紧迫&#xff0c;可以跳到下一节。然而&#xf…

Vue3 依赖注入provide与inject

简介 关于provide与inject下面是vue官网上的一些介绍 通常情况下&#xff0c;当我们需要从父组件向子组件传递数据时&#xff0c;会使用props。想象一下这样的结构&#xff1a;有一些多层级嵌套的组件&#xff0c;形成了一颗巨大的组件树&#xff0c;而某个深层的子组件需要一个…

【Flask开发实战】防火墙配置文件解析(二)之shell读取内容

一、前言 上一篇文章中&#xff0c;介绍了防火墙配置文件包含的基本元素和格式样式&#xff0c;并模拟了几组有代表性的规则内容&#xff0c;作为基础测试数据。在拿到基础测试数据后&#xff0c;关于我们最终想解析成的数据是什么样式的&#xff0c;其实不难看出&#xff0c;…

GateWay路由规则

Spring Cloud GateWay 帮我们内置了很多 Predicates功能&#xff0c;实现了各种路由匹配规 则&#xff08;通过 Header、请求参数等作为条件&#xff09;匹配到对应的路由 1 时间点后匹配 server:port: 8888 spring:application:name: gateway-servicecloud:nacos:discovery:…

四.排序(冒泡/选择)

目录 11-排序介绍 常见排序算法: 12-冒泡排序介绍 代码要求: 思路: 13-冒泡排序 代码: 14-选择排序 简单写法: 好的写法: 11-排序介绍 排序&#xff1a;将一组“无序”的记录序列调整为“有序”的记录序列。 列表排序&#xff1a;将无序列表变为有序列表 输入&#…

C++第七弹---类与对象(四)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、拷贝构造函数 1.1、概念 1.2、特征 2、运算符重载 2.1、等号运算符重载 总结 1、拷贝构造函数 1.1、概念 在现实生活中&#xff0c;可能…