由浅到深认识C语言(12):位段/位域
该文章Github地址:https://github.com/AntonyCheng/c-notes
在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.csdn.net/AntonyCheng/article/details/136555245),该模板集成了最常见的开发组件,同时基于修改配置文件实现组件的装载,除了这些,模板中还有非常丰富的整合示例,同时单体架构也非常适合SpringBoot框架入门,如果觉得有意义或者有帮助,欢迎Star & Issues & PR!
上一章:由浅到深认识C语言(11):结构体
12.位段/位域
这里需要记住,在内存中数据插入输出的顺序,即逆序插入,顺序输出!详解在8.3指针变量中变量的类型;
问题提出:信息在计算机的存取长度一般以 Byte 为单位,但是有时候存储一个信息不必用到一个或者多个 Byte,例如”真“或”假“用 1 或 0 表示即可,只需要 1 bit,此时我们就需要使用位段;
**定义:**C语言允许在一个结构体中以 bit 为单位来指定其成员所占内存长度,以 bit 为单位的成员称为”位段“或称”位域“,而且这些成员的数据类型大都为 unsigned int ,也可以用 unsigned char;
格式示例如下:
struct data
{unsigned int a : 2; //a占2位unsigned int b : 6; //b占6位unsigned int c : 4; //c占4位unsigned int d : 4; //d占4位unsigned int i; //i占32位
}data;
图解如下:
i | d | c | b | a |
---|---|---|---|---|
32bit | 4bit | 4bit | 6bit | 2bit |
而且相邻位域是可以被压缩的,且相邻位域压缩的位数不能超过成员自身的大小;
解释如下: 以下数据类型仅为 unsigned int 和 unsigned char;
若相邻成员数据类型相同(可压缩):
-
如果我们使用的是 unsigned int 类型,最多能够压缩 32 个连续的 unsigned int num : 1; 即最多压缩 32 个 0/1 编码,如果连续的相同数据类型成员位数超过了 4B ,即 32b ,如果大小溢出了 4B ,即大于等于了 33b 的话,进而成为 8B ,如果只压缩了 33 个 unsigned int num : 1 ,无论打印出来是多少 B ,实际大小还是为 33b ,往后以此类推;
-
如果我们使用的是 unsigned char 类型,最多能够压缩 8 个连续的 unsigned char ch : 1; 即最多压缩 8 个 0/1 编码,如果连续的相同数据类型成员位数超过了 1B ,即 8b ,如果大小溢出了 1B ,即大于等于了 9b 的话,进而成为 2B ,如果只压缩了 9 个 unsigned char ch : 1 ,无论打印出来是多少 B ,实际大小还是为 9b ,往后以此类推;
若相邻成员数据类型不同(不可压缩):
不相邻的两个成员或者两类成员,则既要将两类数据内存按照 int 或者 char 基本数据类型的内存进行加减,又要将每一类中的各个成员内存进行压缩;
示例如下:
#include<stdio.h>
#pragma pack(1)
struct bit_data
{unsigned char a : 1;unsigned char b : 1;unsigned char c : 1;unsigned char d : 1;unsigned char e : 1;unsigned char f : 1;unsigned char g : 1;unsigned char h : 1;
}data;int main(int argc, char* argv[]) {printf("data = %d\n", sizeof(data));
}
打印效果如下:
12.1.位段的注意事项
-
位段不能取地址:
因为内存地址是以 Byte 为单位,因为系统内存是以 Byte 为基本单位,系统不会识别在 bit 上的地址;
-
位段的赋值:
不要操作越界的数据,解释如下:
#include<stdio.h>struct bit_data {unsigned char a : 1; //0-1 ==> 0-1unsigned char b : 2; //00-11 ==> 0-3unsigned char c : 3; //000-111 ==> 0-7unsigned char d : 4; //0000-1111 ==> 0-15unsigned char e : 5; //00000-11111 ==> 0-31unsigned char f : 6; //000000-111111 ==> 0-63unsigned char g : 7; //0000000-1111111 ==> 0-127unsigned char h : 8; //00000000-11111111 ==> 0-255 }data;int main(int argc, char* argv[]) {data.a = 1;printf("%u\n", data.a);data.b = 3;printf("%u\n", data.b);data.c = 7;printf("%u\n", data.c);data.d = 15;printf("%u\n", data.d);data.e = 31;printf("%u\n", data.e);data.f = 63;printf("%u\n", data.f);data.g = 127;printf("%u\n", data.g);data.h = 255;printf("%u\n", data.h); }
打印效果如下:
-
无意义位段:
无意义位段用来限制压缩,解释如下:
以下示例将位段定义成了全局变量,可以不用初始化为零值(因为全局变量会自动初始化),但是如果将该位段定义成局部变量,那么就需要我们手动初始化为零,因为局部变量载入时是一个不确定的值;
struct bit_data {unsigned char a : 2;unsigned char : 2; //无意义的位段,仅作占位符,占两个 bitunsigned char b : 2;unsigned char c : 2; }data;
图示如下:
c c b b a a 验证如下:
#include<stdio.h> #include<string.h> struct bit_data {unsigned char a : 2;unsigned char : 2; //无意义的位段,仅作占位符,占两个 bitunsigned char b : 2;unsigned char c : 2; }data;int main(int argc, char* argv[]) {//如果是定义成了局部变量,还需要包含string.h头文件,然后://memset(&data,0,1);data.a = 0;data.b = 2;data.c = 3;//此时data转换成二进制为 1110 0000 ==> 十六进制 0xe0printf("data = %#x\n",data); }
打印效果如下:
-
另起一个位段:
当我们将无意义位段设置为 0 时,我们就成功另起了一个位段,即在内存的另一处重新开辟了一个容器来装下一个位段的内容,证明如下:
#include<stdio.h> #include<string.h> typedef struct data{unsigned char a : 2;unsigned char : 0;unsigned char b : 2;unsigned char : 0;unsigned char c : 2;unsigned char : 0;unsigned char d : 2; }DATA;int main(int argc, char* argv[]) {DATA data;memset(&data, 0, 4);//此时这个结构体里包含了四个位段地址printf("sizeof(data) = %d\n", sizeof(data));data.a = 0;data.b = 1;data.c = 2;data.d = 3;printf("%x\n", data); }
打印效果如下:
12.2.位域和单片机
图解如下:
代码如下:
#include<stdio.h>typedef struct {unsigned char data : 1;unsigned char : 1;unsigned char addr : 2;unsigned char : 1;unsigned char opt : 2;unsigned char : 1;
}DATA;int main(int argc, char* argv[]) {//下面是单片机定义DATA msg;msg.data = 1;msg.addr = 2;msg.opt = 1;
}
上一章:由浅到深认识C语言(13):共用体
相关文章:

由浅到深认识C语言(12):位段/位域
该文章Github地址:https://github.com/AntonyCheng/c-notes 在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.csdn…...

antd5 虚拟列表原理(rc-virtual-list)
github:https://github.com/react-component/virtual-list rc-virtual-list 版本 3.11.4(2024-02-01) 版本:virtual-list-3.11.4 Development npm install npm start open http://localhost:8000/List 组件接收 Props PropDescriptionTypeDefaultchildrenRender …...

机器学习-04-分类算法-03KNN算法
总结 本系列是机器学习课程的系列课程,主要介绍机器学习中分类算法,本篇为分类算法与knn算法部分。 本门课程的目标 完成一个特定行业的算法应用全过程: 懂业务会选择合适的算法数据处理算法训练算法调优算法融合 算法评估持续调优工程化…...

Learn OpenGL 08 颜色+基础光照+材质+光照贴图
我们在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的(Reflected)颜色。物体的颜色为物体从一个光源反射各个颜色分量的大小。 创建光照场景 首先需要创建一个光源,因为我们以及有一个立方体数据,我们只需要进行…...

springboot多模块下swaggar界面出现异常(Knife4j文档请求异常)或者界面不报错但是没有显示任何信息
继上一篇博文,我们解决了多模块下扫描不到子模块的原因,建议先看上一个博客了解项目结构: springboot 多模块启动报错Field XXX required a bean of type XXX that could not be found. 接下来我们来解决swaggar异常的原因,我们成功启动项目…...

【系统架构设计师】系统工程与信息系统基础 01
系统架构设计师 - 系列文章目录 01 系统工程与信息系统基础 文章目录 系列文章目录 前言 一、系统工程 ★ 二、信息系统生命周期 ★ 信息系统建设原则 三、信息系统开发方法 ★★ 四、信息系统的分类 ★★★ 1.业务处理系统【TPS】 2.管理信息系统【MIS】 3.决策支持系统…...

python自动化之(django)(2)
1、创建应用 python manage.py startapp apitest 这里还是从上节开始也就是命令行在所谓的autotest目录下来输入 然后可以清楚的看到 多了一个文件夹 2、创建视图 在views中加入test函数(所建应用下) from django.http import HttpResponse def tes…...

C语言 内存函数
目录 前言 一、memcpy()函数 二、memmove()函数 三、memset函数 四、memcmp()函数 总结 前言 在C语言中内存是我们用来存储数据的地址,今天我们来讲一下C语言中常用的内存函数。 一、memcpy()函数 memcpy()函数与我们之前讲的strcpy()函数类似,只…...

145 Linux 网络编程1 ,协议,C/S B/S ,OSI 7层模型,TCP/IP 4层模型,
一 协议的概念 从应用的角度出发,协议可理解为“规则”,是数据传输和数据的解释的规则。 典型协议 传输层 常见协议有TCP/UDP协议。 应用层 常见的协议有HTTP协议,FTP协议。 网络层 常见协议有IP协议、ICMP协议、IGMP协议。 网络接口层 常…...

【Java】List, Set, Queue, Map 区别?
目录 List, Set, Queue, Map 区别? Collection和Collections List ArrayList 和 Array区别? ArrayList与LinkedList区别? ArrayList 能添加null吗? ArrayList 插入和删除时间复杂度? LinkedList 插入和删除时间复杂度&…...

打卡学习kubernetes——了解k8s基本概念
目录 1 Container 2 Pod 3 Node 4 Namespace 5 Service 6 Label 7 Annotations 8 Volume 1 Container Container(容器)是一种便携式、轻量级的操作系统级虚拟化技术。它使用namespace隔离不同的软件运行环境,并通过镜像自包含软件的运行环境,从而…...

特殊内齿轮加工的另一种选择
内齿轮加工普遍采用插齿或拉削,但对于一些特殊齿廓的内齿轮来说,插齿可能会有一定的困难,或者成本较高。在这种情况下,线切割加工不失为一种不错的选择。那么什么样的零件需要选择这种加工方式呢?一起来看看࿱…...

Visual Studio配置libtorch(cuda安装一步到位)
Visual Studio配置libtorch visual Studio安装cuDNN安装CUDAToolkit安装libtorch下载Visual Studio配置libtorch(cuda版本配置) visual Studio安装 visual Studio点击安装 具体的安装和配置过程这里就不进行细讲了,可以参考我这篇博客Visual Studio配置OpenCV(保姆…...

【工具】一键生成动态歌词字幕
那眼神如此熟悉 让人着迷无力抗拒 一次又一次相遇 在眼前却遥不可及 命运总爱淘气 将一切都藏匿 曾有你的回忆 无痕迹 若不是心心相吸 又怎么会一步一步靠近 🎵 董真《思如雪》 下载LRC歌词 https://www.musicenc.com/article/50287.htmlhttp…...

Linux/Ubuntu/Debian从控制台启动程序隐藏终端窗口
如果你想从终端运行应用程序但隐藏终端窗口. 你可以这样做: 在后台运行: 你只需在命令末尾添加一个与号 (&) 即可在后台运行它。 例如: your_command &将 your_command 替换为你要运行的命令。 这将在后台启动该命令,…...
Android中的设计模式---单例模式
1.什么是单例模式? 单例模式是一种创建型设计模式。它保证一个类只有一个实例,并且这个单例类提供一个函数接口让其他类获取到这个唯一的实例。 2.什么情况下会用到单例? ①频繁访问数据库或文件的对象; ②工具类对象; ③创建对象时耗时过多或耗费资源过多,但又经常用…...
【NLP笔记】文本分词、清洗和标准化
文章目录 文本分词中文分词英文分词代码示例 文本清洗和标准化 文本分词 参考文章:一文看懂NLP里的分词(中英文分词区别3 大难点3 种典型方法); 文本分词处理NLP的基础,先通过对文本内容进行分词、文本与处理(无用标…...

2024 年系统架构设计师(全套资料)
2024年5月系统架构设计师最新第2版教材对应的全套视频教程、历年真题及解析、章节分类真题及解析、论文写作及范文、教材、讲义、模拟题、答题卡等资料 1、2023年11月最新第2版本教材对应全套教程视频,2022年、2021年、2020年、2018年、2016年五套基础知识精讲视频、…...

springboot蛋糕订购小程序的设计与实现
摘 要 相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低商家的运营人员成本,实现了蛋糕订购的标准化、制度化、程序化的管理,有效地防止了蛋糕订购的随意管理,提高了信息的处理速度和精确度,能够及时、准确…...

MongoDB——linux中yum命令安装及配置
一、创建mongodb-org-3.4.repo文件 vi /etc/yum.repos.d/mongodb-org-3.4.repo 将下面内容添加到创建的文件中 [mongodb-org-3.4] nameMongoDB Repository baseurlhttps://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/3.4/x86_64/ gpgcheck1 enabled1 gpgkeyhttps://www…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...