【C语言】结构体实现位段
引言
对位段进行介绍,什么是位段,位段如何节省空间,位段的内存分布,位段存在的跨平台问题,及位段的应用。
✨ 猪巴戒:个人主页✨
所属专栏:《C语言进阶》
🎈跟着猪巴戒,一起学习C语言🎈
目录
引言
什么是位段?
位段的作用
位段是如何节省空间?位段的内存分配
位段的内存分配
位段的跨平台问题
位段的应用
什么是位段?
位段的声明和结构是类似的,有两个不同:
- 位段的成员必须是整形家族的类型
- 位段的成员名后面有一个冒号和一个数字。
冒号后面的数字表示的是这个变量将使用多大的内存(单位是比特位)。
int _n : 2 表示的是_n这个整形变量本来是4个字节(也就是32个比特位) ,但是现在要将它的内存缩减到2个比特位。
struct A
{int _n : 2;int _b : 5;int _c : 10;int _d : 30;
};
整形家族的介绍:
整形类型不仅包括基本整形,还有短整形,长整形,双长整形,字符型和布尔型。

| 类型 | 字节数 | 取值范围 |
| int(整形) | 4 | -2147483648~2147483647 |
| short(短整型) | 2 | -32768~32767 |
| long(长整型) | 4/8 | -2^31~(2^31-1) |
| long long(双长型) | 8 | -2^63~(2^63-1) |
| char | 1 | -2^7~(2^7-1) |
| bool | 1 | 1,0 |
位段的作用
位段的作用就是节省空间。当我们有一些成员的取值范围有限的时候,所需要的内存空间也不需要太多的空间。
比如说布尔类型
只需要表示真或者假,1表示真,0表示假。实际上布尔类型的变量只占有1个比特位,(1个字节代表着8个比特位),如果使用位段就可以帮助我们节省大量的空间。
由此,位段所执行的大小不能大于这个变量类型本身的大小,不然就会报错。

位段是如何节省空间?位段的内存分配
下面是刚才给大家做示范的例子,我们现在看这个位段所占用的空间:
#include <stdio.h>
struct A
{int _n : 2;int _b : 5;int _c : 10;int _d : 30;
};
int main()
{printf("%d\n", sizeof(struct A));return 0;
}

_n,_b,_c,_d这四个变量的大小加在一起,一共是47个比特位,那就是需要6个字节的大小。
但是,我们发现struct A的大小不仅仅是6个字节,而是8个字节。
这就说明位段中内存分布不仅仅是简单组合,顺序地一个紧挨着一个地存放。
位段的内存分配
- 位段的成员可以是整形家族的类型
- 位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的
- 位段涉及很多不确定因素,位段是不跨平台的,注意可移植的程序应该避免使用位段
2.位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的
1.例子
下面位段的大小是8个字节
struct A
{int _n : 2;int _b : 5;int _c : 10;int _d : 30;
};
解析struct A的内存分布:
还是拿这个例子给大家举例:
因为是位段都是int类型,所以这里位段的空间按照4个字节的方式开辟。
首先开辟4个字节来存放内存。
_n是2个比特位,_b是5个比特位,_c是10个比特位,一共是17个比特位
放在4个字节(32个比特位/一个整形大小)当中,剩下15个比特位。
是不足够放下_d(30个比特位),所以另外开辟一个整型大小(4个字节/32个比特位),将_d放进去。
_n,_b,_c放在前面的一个整形,_d放在后面的一个整形。
一共是两个整形,就是8个字节。
2.例子
下面位段的大小是3个字节
#include <stdio.h>
struct S
{char a : 3;char b : 4;char c : 5;char d : 4;
};
int main()
{printf("%d\n", sizeof(struct S));struct S s = { 0 };s.a = 10;s.b = 12;s.c = 3;s.d = 4;return 0;
}

解析struct S位段的内存分布:
这个位段都是char 类型,所以这里位段的空间按照1个字节的方式开辟。
1.首先开辟1个字节(8个比特位),来存放数据
a是3个比特位,b是4个比特位,那么开辟的第一个字节就剩下1个比特位,是不足够存放5个比特位的c变量。
2.开辟下一个字节(8个比特位)存放数据
c是5个比特位,这个字节还剩下3个比特位,不足够存放4个比特位的d变量。
3.开辟下一个空间(8个比特位)存放数据
d是4个比特位,将d存放第三个字节中。
解析struct S的数据在内存中的具体分布:
//在位段中的成员被赋值后,观察内存分布
struct S s = { 0 };
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
struct S在内存中的分布其实是有所差异的,当位段中的成员被赋值后,我们就可以看到位段中的成员是如何分布的。
首先开辟一个字节后,
a=10的二进制数字是01010,位段:3个比特位,所以a的值放入内存中会被裁断,变成010.
b的值是12,位段:4个比特位,所以b存到内存中的值是1100.(数据是以二进制的形式存到内存)
a,b的存放方式如下图:a和b在第一个字节中的排列方式是从右到左的,也就是从高地址向低地址,在一个字节中优先排放高地址。
第二个字节开辟,
c=3的二进制数字是11,位段:5个字节,不足5个字节用0来补充高位,也就是00011.
c的存放方式也是在这个字节中优先排放高地址处。
第三个字节开辟,
d的值是4,二进制数字是100,位段:4个字节,高位用o来补充,也就是0100
d的存放方式也是在这个字节中优先排放高地址处。
所以位段struct S在内存中存放的数据是01100010 00000011 00000100
换算成十六进制数字就是 62 03 04
验证:
通过内存调试,观察内存窗口就可以看到

位段的跨平台问题
- int 位段被当成有符号数还是⽆符号数是不确定的。
- 位段中最⼤位的数⽬不能确定。(16位机器最⼤16,32位机器最⼤32,写成27,在16位机器会出问题。
- 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
- 当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,是舍弃剩余的位还是利⽤,这是不确定的。
总结:
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。
位段的应用
相关文章:
【C语言】结构体实现位段
引言 对位段进行介绍,什么是位段,位段如何节省空间,位段的内存分布,位段存在的跨平台问题,及位段的应用。 ✨ 猪巴戒:个人主页✨ 所属专栏:《C语言进阶》 🎈跟着猪巴戒,…...
IEEE RAS 机器人最优控制(Model-based Optimization for Robotics)学习资料
系列文章目录 前言 电气和电子工程师学会机器人模型优化技术委员会 一、学习资料 1.1 教程和暑期学校 2020 年 Memmo 欧盟项目暑期班2019年Memmo欧盟项目冬季学校Matthias Gerdts(德国慕尼黑联邦国防军大学)在拜罗伊特 OMPC 2013 上举办的最优控制教程…...
redis中缓存雪崩,缓存穿透,缓存击穿等
缓存雪崩 由于原有缓存失效(或者数据未加载到缓存中),新缓存未到期间(缓存正常从Redis中获取,如下图)所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,…...
C_8练习题答案
一、单项选择题(本大题共20小题,每小题2分,共40分。在每小题给出的四个备选项中,选出一个正确的答案,并将所选项前的字母填写在答题纸的相应位置上。) 编写C语言程序一般需经过的几个步骤依次是(B)。A.编辑、调试、编译、连接 B.编辑、编译、连接、运行 C.编译、调试、编辑、连…...
Web漏洞分析-文件解析及上传(中)
随着互联网的迅速发展,网络安全问题变得日益复杂,而文件解析及上传漏洞成为攻击者们频繁攻击的热点之一。本文将深入研究文件解析及上传漏洞,通过对文件上传、Web容器IIS、命令执行、Nginx文件解析漏洞以及公猫任意文件上传等方面的细致分析&…...
使用Node.js创建接口
当使用Node.js创建接口时,有两种主要方式:使用Express框架和使用Node.js的HTTP模块。 Express框架方式: 总的来说,使用Express框架可以更快速地搭建和管理接口,而使用Node.js的HTTP模块则提供了更多底层控制和灵活性&…...
【起草】人人都应该有一个chatGPT助手
第一章:ChatGPT 简介 - 介绍 ChatGPT 的基本概念和工作原理 - 讨论 ChatGPT 在自然语言处理领域的重要性和应用价值 【起草】章节 1-1 介绍 ChatGPT 的基本概念和工作原理-CSDN博客 【起草】1-2 讨论 ChatGPT 在自然语言处理领域的重要性和应用价值-CSDN博客…...
TCP/IP详解——网络基本概念
文章目录 一、网络基本概念1. OSI 7层模型1.1 每层对应的协议1.2 每层涉及的设备1.2.1 物理层设备1.2.2 数据链路层设备1.2.3 网络层设备1.2.4 传输层设备1.2.5 交换机和路由器的应用1.2.6 问题 2. TCP/IP 4层模型3. 物理层传输介质3.1 冲突域 4. 数据链路层4.1 以太网帧结构4.…...
[Linux] ps命令详解
ps命令 ps命令用于显示当前系统中的进程状态信息。以下是ps命令的一些常见参数及其作用: ps命令的基本形式: ps这将显示当前用户自己的运行中的进程的快照。 参数选项: -a: 显示所有进程,包括其他用户的进程。 -u: 显示与用户相…...
QT 中基于 TCP 的网络通信 (备查)
基础 基于 TCP 的套接字通信需要用到两个类: 1)QTcpServer:服务器类,用于监听客户端连接以及和客户端建立连接。 2)QTcpSocket:通信的套接字类,客户端、服务器端都需要使用。 这两个套接字通信类…...
使用MIB builder自定义物联网网关的MIB结构
文章目录 物联网网关初识(了解即可)IoT的通用MIB库结构MIB Builder开发流程指导问题总结子叶没所属分组值范围不为0 物联网网关初识(了解即可) 网关又称网间连接器、协议转换器。简单说,物联网网关是一台智能计算机&a…...
特权FPGA学习笔记
C/C/system C-----vivado HLS------------->RTL门电路,省去了HDL语言的中间转换,可以看作是C向C#的演进,基于zynq面向以前使用C的开发人员,但是个人觉得,HDL存在且未被C取代,工具的着眼点就是面向底层调…...
利用阿里云 DDoS、WAF、CDN 和云防火墙为在线业务赋能
在这篇博客中,我们将详细讨论使用阿里云 CDN 和安全产品保护您的在线业务所需的步骤。 方案描述 创新技术的快速发展为世界各地的在线业务带来了新的机遇。今天的人们不仅习惯了,而且依靠互联网来开展他们的日常生活,包括购物、玩游戏、看电…...
Mysql的事务日志
Mysql的事务具有四个特性:原子性、一致性、隔离性、持久性。那么事务的四种特性分别是靠什么机制实现的呢? 事务的隔离性由锁机制来保证 事务的原子性、一致性、持久性则由redo log和Undo log来保证。 - redo log是重做日志,提供再写入操作&…...
三、Shell 环境
一、Linux 系统分类 在 Linux 中,常见的 Shell 有以下几种: Bourne Shell(sh):最早的 Shell,由 Stephen Bourne 开发。它是大多数其他 Shell 的基础。Bourne Again Shell(bash)&am…...
2023年第三届产业数字化【金铲奖】重磅来袭!
做具备产业数字化价值的企业、案例标杆、资本机构的见证者、发现者、陪伴者。 出品|产业家 一年一度的金铲奖来了! 在过去的一年时间里,我们清晰地看到,产业数字化的潮水更加汹涌澎湃且势不可挡,越来越多的企业开始寻求数字化…...
node.js安装和配置
软件介绍 Node.js是一个免费的、开源的、跨平台的JavaScript运行时环境,允许开发人员在浏览器之外编写命令行工具和服务器端脚本。 Node.js是一个基于Chrome JavaScript运行时建立的一个平台。 Node.js是一个事件驱动I/O服务端JavaScript环境,基于Googl…...
【周报2023.12.09】
周报2023.12.09 本周开展工作下周工作计划 本周开展工作 本周开展的工作的话一共是一下几点: 这三点的话是紧密相连的 逻辑这边需要考虑的东西很多 点击生成照片,然后获取生成照片的状态点击生成照片,然后获取生成照片的时间,并…...
基于ssm大学生创新创业平台项目管理子系统设计与实现论文
摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对大学生创新创业项目信息管理混乱,出错率高,信…...
JS基础之原型原型链
JS基础之原型&原型链 原型&原型链构造函数创建对象prototypeprotoconstructor实例与原型原型的原型原型链其他constructorproto继承 原型&原型链 构造函数创建对象 我们先使用构造函数创建一个对象: function Person(){ } var person new Person();…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
Android写一个捕获全局异常的工具类
项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler,它是Thread的子类(就是package java.lang;里线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都…...
「Java基本语法」变量的使用
变量定义 变量是程序中存储数据的容器,用于保存可变的数据值。在Java中,变量必须先声明后使用,声明时需指定变量的数据类型和变量名。 语法 数据类型 变量名 [ 初始值]; 示例:声明与初始化 public class VariableDemo {publi…...

✨ 猪巴戒:个人主页✨

