【C语言】位段(结构体实现位段)

目录

一、位段的定义

二、位段的声明

三、位段的内存分配

四、位段在内存中的存储方式

五、位段的优点

六、位段的跨平台问题

七、位段的应用

八、位段使用的注意事项


一、位段的定义

信息的存取一般以字节为单位。实际上,有时存储一个信息不必用一个或多个字节。

例如:"真"或"假"可以用0或1表示,只需1位即可。这时我们就可以用位段来进行存储。

那么什么是位段呢?

        位段(Bit Field)是C语言中的一种数据结构,它允许程序员在一个结构体中以位为单位来指定其成员所占的内存长度。这种以位为单位的成员称为"位段""位域"

        位段的定义要借助于结构体,即以二进制位为单位定义结构体成员所占存储空间,从而可以按"位"来访问结构体中的成员。

        位段与结构体形式与用法上是很相近的,但位段可以用来描述更为细腻的数据级别。

二、位段的声明

位段的声明语法形式如下:

struct   标签

{

    位段成员类型 位段成员名:分配内存的大小;

}

举例:

struct A
{int _a : 2;  //分配2bit的空间大小int _b : 5;	 int _c : 10;int _d : 30;
};
//A就是一个位段类型
//int:位段的成员类型   _a: 位段成员名   2:分配内存的大小 

注意:

  1. 位段的成员必须是(整型):int,unsigned int 或signed int,char
  2. 位段的成员名后边有一个冒号和一个数字
  3. 位段成员名中的 "_" 是可以是可以省略的,加上下划线与不加都可以,只是一种命名风格。
  4. 位段中分配内存的大小,宽度必须小于等于指定类型的位宽度。(即:冒号后面的数字的bit不能超过前面类型所占的bit
  5. 位段的位指的是二进制位
  6. 位段的声明应在结构体/联合体中。

    原因:

    位段是依赖结构体/联合体来实现的。在位段的声明和使用中,虽然可以决定用多少位来存储数据,但不能认为位段就是可以自定义的数据类型。可以理解为:位段是依赖于结构体实现的自定义类型。可以认为位段是将一个盒子里面的格子自定义大小。

三、位段的内存分配

位段所占内存大小为多少呢?

我们测试下面一段代码:

struct S
{char _a : 3;char _b : 4;char _c : 5;char _d : 4;
};int main()
{printf("%d\n", sizeof(struct S));return 0;
}

测试结果如图所示:

为什么会是3个字节(byte)呢?

原因:

  1. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
  2. 一个位段必须存储在同一存储单元(即字)之中,不能跨两个单元。如果其单元空间不够,则剩余空间不用,从下一个单元起存放该位段。

四、位段在内存中的存储方式

我们看如下一段代码:

#include <stdio.h>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;
}

调试结果如下:

我们调试发现:

10,12,3,4在内存中是以16进制存放,为什么是62 03 04呢?

分析如下:

可知:位段中的成员在内存中是从右向左分配。

注意:

  1. 大小端指的是如果一个数据存储时超过一个字节的时候,才有字节顺序。这里是一个字节(内部),所以不谈顺序。
  2. 这里是先开辟一个字节,再开辟一个字节,最后再开辟一个字节,所以存放顺序一定是如图所示的存放方式。

五、位段的优点

 可以使数据单元节省储存空间,避免不必要的空间浪费。

 但是所谓节省空间是在一定程度上节省空间,并不是完全不浪费。

六、位段的跨平台问题

        1、int被位段作为是:无符号整数还是有符号整数,这个并没有做出明确的规定。

        2、位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器就会出现问题)

        3、位段中的成员在内存中是从左向右分配,还是从右向左分配尚未定义。(vs中是从右向左)

        4、当一个结构包含两个位段,假设第二个位段成员无法全部容纳于第一个剩余的位时,是把一个空间填满再放到新开辟的空间,还是直接全部放到新的空间,这个没有明确的规定。(vs中是直接全部放到新的空间)

补充:

  • 只有在位段的时候,int是没有确定是使用unsigned还是signed。除此之外int都是signed int。
  •  而char才是在使用和不使用位段的时候都是不确定的。

总结:位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

七、位段的应用

        1、在一些特定的应用场景中,需要对一个整数类型的变量中的每一位进行单独的控制或访问。例如,硬件寄存器常包含一些特定的位用于表示设备的状态,配置选项或标志位。使用位段可以让程序员更方便地访问和控制这些位,不需要进行位运算。

        2、在网络协议中,IP数据报的格式。可以看到其中很多属性只需要几个bit位就能描述,使用位段就能够实现想要的效果,也节省了空间,这样网络传输的数据报大小也会较小一些,对网络的畅通是有帮助的。

八、位段使用的注意事项

1、位段无地址,不能对位段进行取地址运算。

原因:

位段的几个成员共用一个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位置处是没有地址的。

因为内存中是每个字节分配一个地址,一个字节内部的bit位是没有地址的。

所以不能对位段的成员使用&操作符,这样就不能使用scanf直接对位段的成员输入值,只能是先输入一个值存放在一个变量中,然后再赋值给位段的成员。

如下所示:

#include <stdio.h>struct A
{int _a : 2;int _b : 5;int _c : 10;int _d : 30;
};int main()
{struct A sa = { 0 };scanf("%d", &sa._b); //这是错误的//正确的示范int b = 0;scanf("%d", &b);sa._b = b;return 0;
}

2、位段里的成员类型要尽量保持一致。否则会带来没必要麻烦,它内存开辟的时候可能会跟期望的不一样。

原因:

位段使用的场景本来就非常苛刻。如果再类型不一样,这样写出来的代码可控性就会变得差,而且它有许多不确定性,导致了它的不跨平台性。

3、位段在访问时与结构体访问方式相同,通过点操作(.)进行访问。访问时注意不要超出了所定义的位段大小。

4、两位段相邻时,相同数据类型的位段在编译过程中可以提高存储效率,而不同数据类型的位段则更可能需要考虑数据对齐而降低存储效率。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

经典获奖案例 | 度小满互联网金融开源软件治理解决方案

近日&#xff0c;广东省粤港澳合作促进会金融专业委员会和粤港澳大湾区金融创新研究院在广州联合举办“2024年粤港澳大湾区数智金融峰会暨第二届金融创新优秀应用案例与解决方案技术成果授牌仪式”。《度小满互联网金融开源软件治理解决方案》从数百个申报项目中脱颖而出&#…

Java面试八股之死锁和饥饿的区别

死锁和饥饿的区别 定义与现象&#xff1a; 死锁&#xff08;Deadlock&#xff09;是指两个或多个线程互相等待对方持有的资源而无法继续执行的情况。每个线程至少持有一个资源&#xff0c;并尝试获取另一个由其他线程持有的资源&#xff0c;从而形成一个循环等待的僵局&#…

Python 图书馆管理系统(MySQL数据库) 有GUI界面 【含Python源码 MX_032期】

使用python3&#xff0c;PyQt5&#xff0c;MySQL数据库搭建 主要功能&#xff1a; 用户注册、登录、修改密码、用户管理存储图书信息、采购增加和淘汰删除功能、租借功能实现图书采购、淘汰、租借功能。实现查询图书信息、采购和淘汰、库存、和租借情况实现统计图书的采购、库…

多输入多输出非线性对象的模型预测控制—Matlab实现

本示例展示了如何在 Simulink 中设计多输入多输出对象的闭环模型预测控制。该对象有三个操纵变量和两个测量输出。 一、非线性对象的线性化 运行该示例需要同时安装 Simulink 和 Simulink Control Design。 % 检查是否同时安装了 Simulink 和 Simulink Control Design if ~m…

【Python】【matLab】模拟退火算法求二元高次函数最小值

一、目标函数 求二元高次函数的最小值。目标函数选择&#xff1a; 用于测试算法的简单的目标函数&#xff1a; 二、Python代码实现 import numpy as np# 目标函数&#xff08;2变量&#xff09; def objective_function(x):return x[0] ** 2 2 * x[0] - 15 4 * 4 * 2 * x[…

Flutter:革新移动开发的开源框架

在今天的移动应用开发领域&#xff0c;Flutter 已成为最受欢迎的开源框架之一。由 Google 开发并在 2017 年发布&#xff0c;Flutter 允许开发者使用单一代码库来构建跨平台的高性能应用&#xff0c;有效地覆盖了 iOS 和 Android 两大平台。接下来&#xff0c;我们将深入探索 F…

深度学习-05-反向传播理论知识

深度学习-05-反向传播理论知识 本文是《深度学习入门2-自製框架》 的学习笔记&#xff0c;记录自己学习心得&#xff0c;以及对重点知识的理解。如果内容对你有帮助&#xff0c;请支持正版&#xff0c;去购买正版书籍&#xff0c;支持正版书籍不仅是尊重作者的辛勤劳动&#xf…

密码学基础概念

加密性 什么是加密&#xff1f; 1.对原有的明文数据&#xff0c;执行某种运算&#xff0c;得到密文数据。 2.密文数据对于未授权人员而言&#xff0c;在一定上程度上加大了解读的难度 3.加密功能用于实现机密性 什么是密钥&#xff1f; 1.如同持有保险柜钥匙才能打开保险柜…

HTML基本元素包含HTML表单验证

可将以下代码复制另存为一个HTML文件浏览器打开自己去看看实际使用效果 <!DOCTYPE html> <html> <head> <meta charset"utf-8"><title>测试</title> </head> <body> <h1>很多事</h1> <h1><b&…

【linux】开机调用python脚本

linux中&#xff0c;可以使用crontab 设置开机自动调用 crontab的安装在前面文章里写过了&#xff0c;不再重复 首先&#xff0c;还是进入crontab配置文件 crontab -e 进入之后&#xff0c;跟其他定时任务不同&#xff0c;只需要在时间配置那里用rebooot 这类之后的两个文件的…

生成随机图片

package com.zhuguohui.app.lib.tools;/*** Created by zhuguohui* Date: 2024/6/1* Time: 13:39* Desc:获取随机图片*/ public class RandomImage {// static final String url "https://picsum.photos/%d/%d?random%d";static final String url "https://…

力扣174题动态规划:地下城游戏(含模拟面试)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业…

贝锐向日葵分组策略:减少重复操作,提升管理效率

面对大数量级的IT设备&#xff0c;如何高效实施管理是运维的关键所在&#xff0c;如何快速准确的对大量的设备按需分组&#xff0c;则是管理精准触达的第一步。 但是&#xff0c;传统的分组方式应付少量设备还可行&#xff0c;设备数量级一旦来到上千台甚至更多时&#xff0c;…

计算机视觉与模式识别实验2-1 角点检测算法(Harris,SUSAN,Moravec)

文章目录 &#x1f9e1;&#x1f9e1;实验流程&#x1f9e1;&#x1f9e1;Harris算法SUSAN算法Moravec算法 &#x1f9e1;&#x1f9e1;全部代码&#x1f9e1;&#x1f9e1; &#x1f9e1;&#x1f9e1;实验流程&#x1f9e1;&#x1f9e1; Harris算法 Harris算法实现步骤&…

重学java 59.Properties属性集集合嵌套集合下总结

不要咀嚼小小悲观&#xff0c;而忘掉整个世界 —— 24.6.3 一、Properties集合&#xff08;属性集&#xff09; 1.概述 Properties 继承 于HashTable 2.特点 a、key唯一&#xff0c;value可重复 b、无序 c、无索引 d、线程安全 e、不能存null键&#xff0c;null值 f、Propertie…

AI 赋能前端 -- 文本内容概要生成

幸福不在于你获得了什么,而在于你比他人多获得了什么 是比较出来的 大家好,我是柒八九。一个专注于前端开发技术/Rust及AI应用知识分享的Coder 此篇文章所涉及到的技术有 OpenAILangChainRust/WebAssemblyWeb Workerreact+ts+vite配置环境变量(env)因为,行文字数所限,有些概…

前端将DOM元素导出为图片

前端工作中经常会用到把一些元素导出&#xff0c;比如表格&#xff0c;正好项目有遇到导出为excel和导出为图片&#xff0c;就都封装实现了一下&#xff0c;以供其他需求的开发者使用&#xff1a; 1.导出为文档 这个说白了就是下载的功能&#xff0c;传过去检索参数&#xff…

小熊家务帮day10- 门户管理

门户管理 1 门户介绍1.1 介绍1.2 常用技术方案 2 缓存技术方案2.1 需求分析2.1.1 C端用户界面原型2.1.2 缓存需求2.1.3 使用的工具 2.2 项目基础使用2.2.1 项目集成SpringCache2.2.2 测试Cacheable需求Service测试 2.1.3 缓存管理器&#xff08;设置过期时间&#xff09;2.1.4 …

使用软件分享--剪映(不需要会员版)剪映 Jianying_pro_3_2_0_8778_beta9_jianyingpro_beta(Windows)

专栏介绍&#xff1a;本专栏主要分享一些实用的软件&#xff08;Po Jie版&#xff09;&#xff1b; 声明1&#xff1a;软件不保证时效性&#xff1b;只能保证在写本文时&#xff0c;该软件是可用的&#xff1b;不保证后续时间该软件能一直正常运行&#xff1b;不保证没有bug&am…

关于网络编程

目录 1、InetAdress类 2、Socket套接字 3、UDP数据报套接字编程 &#xff08;1&#xff09;DatagramSocket 类 &#xff08;2&#xff09;DatagramPacket类 &#xff08;3&#xff09;处理无连接问题 UdpEchoServer.java UdpEchoClient.java 4、TCP流套接字编程 &…