当前位置: 首页 > news >正文

学懂C语言(二十五):深入理解 C语言结构体 位域 的概念

        

目录

一、位域的基本概念

二、位域的定义

三、位域的内存分配和大小计算

示例1:简单位域

示例2:跨越多个存储单元

注意事项

结构体对齐控制

总结


        C语言中的位域(Bit-Field)是一种特殊的数据结构,允许在结构体中定义占用特定位数的成员,主要用于节省存储空间并简化对特定位数数据的操作。位域一般用于需要紧凑表示某些标志(flags)或状态的场景,如硬件寄存器的模拟、协议头的解析等。以下是对C语言位域知识点的详细讲解。

一、位域的基本概念

  • 定义:位域是指把一个字节(或其他整数类型)中的二进制位划分为几个不同的区域,每个区域有不同的位数,并允许在程序中通过域名来访问这些区域。
  • 目的:通过仅占用必要的位数来存储数据,从而节省存储空间。

二、位域的定义

位域的定义与结构体的定义类似,但每个成员后面会跟随一个冒号和该成员所占的位数。定义形式如下:

struct 位域结构名 {  类型说明符 位域名:位域长度;  ...  
};
  • 类型说明符:指定了位域的类型,如intunsigned intchar等。需要注意的是,位域的类型必须是整数类型。
  • 位域名:为位域指定的名称,用于在程序中引用该位域。
  • 位域长度:指定了位域占用的位数,这个长度必须小于或等于指定类型的位宽度。

示例:

struct BitField {unsigned int flag : 1;unsigned int value : 3;unsigned int mode : 4;
};

在这个例子中:

  • flag 占用 1 位。
  • value 占用 3 位。
  • mode 占用 4 位。

三、位域的内存分配和大小计算

位域的内存分配和大小计算可能会因编译器和平台的不同而有所差异,但一般遵循以下原则:

  1. 相邻位域字段类型相同
    • 如果相邻位域字段的类型相同,且其位宽之和小于或等于类型的sizeof大小(注意这里是指类型的位数,而不是sizeof操作符返回的字节数),则后面的字段将紧邻前一个字段存储,直到不能容纳为止。
    • 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍(以字节为单位,但实际对齐到的是位)。
  2. 相邻位域字段类型不同
    • 这种情况下,不同编译器的实现可能有所不同。一些编译器可能会将不同类型的位域字段存放在不同的字节中,以确保对齐和访问效率。
  3. 结构体的总大小
    • 结构体的总大小通常是其最宽基本类型成员大小的整数倍,以满足内存对齐的要求。这意味着即使所有位域成员的总位数远小于一个字节,结构体也可能占用多个字节的内存。 
示例1:简单位域
#include <stdio.h>struct BitField {unsigned int flag : 1;unsigned int value : 3;unsigned int mode : 4;
};int main() {printf("Size of struct BitField: %lu bytes\n", sizeof(struct BitField));return 0;
}

在这个例子中:

  • flag 占用 1 位。
  • value 占用 3 位。
  • mode 占用 4 位。

总共:1 + 3 + 4 = 8 位,即1字节。但是,由于unsigned int一般需要4字节对齐,编译器可能会将整个结构体对齐到4字节。

Size of struct BitField: 4 bytes
示例2:跨越多个存储单元
#include <stdio.h>struct BitField {unsigned int a : 1;unsigned int b : 15;unsigned int c : 17;
};int main() {printf("Size of struct BitField: %lu bytes\n", sizeof(struct BitField));return 0;
}

在这个例子中:

  • a 占用 1 位。
  • b 占用 15 位。
  • c 占用 17 位。

总共:1 + 15 + 17 = 33 位。由于unsigned int一般是4字节(32位),所以需要两个unsigned int存储。

Size of struct BitField: 8 bytes
注意事项
  1. 内存对齐:编译器可能会为满足硬件对齐要求而进行填充,这会影响结构体的大小。
  2. 平台相关性:不同编译器和不同硬件平台可能会对位域的大小和对齐方式有不同的处理方式。
  3. 跨平台兼容性:由于上述差异,位域在不同平台上的兼容性可能存在问题,需要小心处理。
  4. 性能考虑:尽管位域可以节省内存,但在某些平台上,操作位域的性能可能会较低,因为这些操作可能需要额外的指令来处理位操作。

为了确保结构体的大小符合预期,可以使用#pragma pack或其他编译器指令来控制对齐方式,但这需要根据具体情况谨慎使用。

结构体对齐控制

使用#pragma pack可以控制结构体的对齐方式,以确保结构体大小符合预期。

#include <stdio.h>#pragma pack(push, 1)
struct PackedBitField {unsigned int flag : 1;unsigned int value : 3;unsigned int mode : 4;
};
#pragma pack(pop)int main() {printf("Size of struct PackedBitField: %lu bytes\n", sizeof(struct PackedBitField));return 0;
}

在这个例子中,我们使用#pragma pack(push, 1)来将结构体对齐到1字节。

Size of struct PackedBitField: 1 bytes

这样可以确保结构体大小为1字节,且没有额外的填充位。

总结

C语言的位域是一种强大的数据结构,可以帮助开发者在节省存储空间的同时,方便地操作特定位数的数据。然而,由于编译器和平台的差异,位域的内存分配和大小计算可能会变得复杂。因此,在使用位域时,需要仔细考虑这些因素,并确保代码的可移植性和健壮性。

相关文章:

学懂C语言(二十五):深入理解 C语言结构体 位域 的概念

目录 一、位域的基本概念 二、位域的定义 三、位域的内存分配和大小计算 示例1&#xff1a;简单位域 示例2&#xff1a;跨越多个存储单元 注意事项 结构体对齐控制 总结 C语言中的位域&#xff08;Bit-Field&#xff09;是一种特殊的数据结构&#xff0c;允许在结构体中…...

LLM推理优化——KV Cache篇(百倍提速)

LLM推理优化——KV Cache篇&#xff08;百倍提速&#xff09; 注意&#xff1a;KV Cache本质上是空间换时间的技术。与计算机组成原理中的cache不同&#xff0c;它不涉及访存优化。 不知道大家在用LLM的时候&#xff0c;有没有注意到一个问题&#xff1a;我们在输入我们的问题…...

Linux进程--system

...

[Office] Word 特殊字符

0 打开“特殊字符集” 依次选择&#xff1a;Insert -> Symbol -> More Symbol 1 带圈编号 字体Font选择Wingdings...

联想电脑怎么重装系统_联想电脑U盘重装win10详细图文教程

联想电脑怎么重装系统&#xff1f;在当今科技发展迅猛的时代&#xff0c;联想电脑已经成为了人们生活中不可或缺的一部分。然而&#xff0c;随着时间的推移&#xff0c;我们可能会遇到一些问题&#xff0c;例如系统崩溃或者需要更换操作系统。这时&#xff0c;使用U盘来重新安装…...

前端开发者必备:揭秘谷歌F12调试的隐藏技巧!

前言 使用断点&#xff08;breakpoint&#xff09;是调试 JavaScript 代码的一种非常有效的方式。通过在代码的关键位置设置断点&#xff0c;可以阻止页面的状态变化&#xff0c;从而方便地检查和修改页面的当前状态。 1. 使用 setTimeout 配合 debugger 和 console.log setTi…...

vivado IP_REPO_PATHS

此属性允许您创建自定义IP目录&#xff0c;以与Vivado Design Suite一起使用。 IP_REPO_PATHS属性定义了一个或多个目录的路径&#xff0c;这些目录包含 第三方或用户定义的IP。指定的目录和任何子目录是 搜索要添加到Vivado Design Suite IP目录以用于设计的IP定义 进入或与IP…...

前端代码混淆加密(使用Terser、WebpackObfuscator)

零、相关技术及版本号 "vue": "2.6.12", "vue/cli-service": "4.4.6", "javascript-obfuscator": "^4.1.1", "terser-webpack-plugin": "^4.2.3", "vue-template-compiler": &quo…...

【复读EffectiveC++24】条款24:若所有参数皆需类型转换,请为此采用non-member函数

条款24&#xff1a;若所有参数皆需类型转换&#xff0c;请为此采用non-member函数 一、问题引入 举个例子&#xff0c;如果你设计一个表示有理数的类&#xff0c;允许从整型到有理数的隐式转换应该是合理的。在C内置类型中&#xff0c;从int转换到double也是再合理不过的了&a…...

Mac应用快速启动器:Alfred 5 for Mac 激活版

Alfred 5 是一款专为 macOS 系统设计的效率提升工具。这款软件以其快速启动和高效操作功能著称&#xff0c;通过使用快捷键来呼出输入界面&#xff0c;用户可以快速完成各种任务。 最新版本 Alfred 5.5 引入了一些新功能。其中包括整合了 ChatGPT 和 DALL-E&#xff0c;这意味…...

oracle语法介绍

Oracle数据库是关系型数据库管理系统之一&#xff0c;其SQL语法遵循标准的SQL规范&#xff0c;但也有一些自己的扩展。以下是一些Oracle SQL语法的基本示例&#xff1a; 1.选择数据&#xff1a; SELECT * FROM my_table; 1.插入数据&#xff1a; INSERT INTO my_table (colum…...

Python IDLE修改JetBrains Mono字体教程

自己在使用Python IDLE过程中发现原生字体不好看&#xff0c;不美观。尤其是对于部分字符&#xff0c;l打印不美观&#xff0c;区别不明显。于是诞生了换字体的想法。 教程简单&#xff0c;快速&#xff0c;3-5分钟不到即可完成。 目录 选型 下载安装 使用 选型 考虑到代码…...

CCF编程能力等级认证GESP—C++1级—20240629

CCF编程能力等级认证GESP—C1级—20240629 单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09;判断题&#xff08;每题 2 分&#xff0c;共 20 分&#xff09;编程题 (每题 25 分&#xff0c;共 50 分)休息时间立方数 单选题&#xff08;每题 2 分&#xff0c;共 30…...

继HBM之后, 内存领域新宠MCR DIMM闪亮登场!

随着人工智能&#xff08;AI&#xff09;和大数据的迅速发展&#xff0c;新型DRAM正迎来新的发展机遇。在服务器需求的推动下&#xff0c;MCRDIMM作为内存行业的新宠儿&#xff0c;正逐步登上历史舞台。 扩展阅读&#xff1a;MCR DIMM如何解决内存带宽瓶颈&#xff1f; MCR DIM…...

谷粒商城实战笔记-75-商品服务-API-品牌管理-品牌分类关联与级联更新

文章目录 一&#xff0c;引入Mybatis Plus分页插件二&#xff0c;品牌列表的模糊查询三&#xff0c;增加品牌测试数据四&#xff0c;开发后台品牌关联分类接口1&#xff0c;接口product/categorybrandrelation/catelog/list2&#xff0c;接口product/categorybrandrelation/sav…...

Java中的equals()与==的区别与用法

1. 区别 “”操作符用于比较两个对象的地址是否相等。.equals() 方法用于比较两个对象的内容是否相等。 Object 类的 .equals() 方法默认采用的是“”操作符进行比较。假如子类没有重写该方法的话&#xff0c;那么“”操作符和 .equals() 方法的功效就完全一样——比较两个对…...

【ai】 2005年 rule based expert system学习笔记1

PPT 是2005年的? Negnevitsky, Pearson Education 使用两种推理引擎的选择 backward chaining(逆向链接)推理过程 backward chaining(逆向链接)推理过程的GPT解释 这幅图展示了一个基于规则的专家系统如何通过backward chaining(逆向链接)推理过程来达到最终的推理目标…...

AI写作|去除了AI味道,我还花2分钟动手制作了一个coze智能体

本文背景&#xff1a; AI写出来的东西&#xff0c;机器味太浓&#xff1f; AI生成的文章内容质量不稳定、因为依赖于已有的数据和模式&#xff0c;AI可能很难创作出具有深度见解或独创性的内容 AI还无法完全理解复杂的上下文关系&#xff0c;导致生成的内容与用户期望的上下文不…...

数据集相关类代码回顾理解 | utils.make_grid\list comprehension\np.transpose

目录 utils.make_grid list comprehension np.transpose utils.make_grid x_gridutils.make_grid(x_grid, nrow4, padding2) make_grid 函数来自torchvision的utils模块&#xff0c;用于图像数据可视化&#xff0c;将一批图像排列成一个网格。 x_grid&#xff1a;四维图像…...

React前端面试每日一试 3.状态(State)和属性(Props)的区别是什么?

加粗样式先简单介绍一下Props和State的特点 Props&#xff08;属性&#xff09; Props&#xff08;Properties&#xff09;是React组件间传递数据的一种方式。它们是从父组件传递给子组件的只读数据&#xff0c;子组件不能修改这些数据。Props主要用于配置组件&#xff0c;使…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题&#xff1a; pgsql数据库通过备份数据库文件进行还原时&#xff0c;如果表中有自增序列&#xff0c;还原后可能会出现重复的序列&#xff0c;此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”&#xff0c;…...

深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙

WebGL&#xff1a;在浏览器中解锁3D世界的魔法钥匙 引言&#xff1a;网页的边界正在消失 在数字化浪潮的推动下&#xff0c;网页早已不再是静态信息的展示窗口。如今&#xff0c;我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室&#xff0c;甚至沉浸式的V…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式

pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图&#xff0c;如果边框加在dom上面&#xff0c;pdf-lib导出svg的时候并不会导出边框&#xff0c;所以只能在echarts图上面加边框 grid的边框是在图里…...