C++ bit field 位域/位段
“ 位域 “ 或 “ 位段 “(Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作。这种数据结构的一个好处是它可以使数据单元节省储存空间,当程序需要成千上万个数据单元时,这种方法就显得尤为重要。第二个好处是位段可以很方便的访问一个整数值的部分内容从而可以简化程序源代码。而这种数据结构的缺点在于,位段实现依赖于具体的机器和系统,在不同的平台可能有不同的结果,这导致了位段在本质上是不可移植的。
- 位域在内存中的布局是与机器有关的
- 位域的类型必须是整型或枚举类型,带符号类型中的位域的行为将因具体实现而定
- 取地址运算符(&)不能作用于位域,任何指针都无法指向类的位域
1、位域使用
位域通常使用结构体声明, 该结构声明为每个位域成员设置名称,并决定其宽度:
例如:
struct _PRCODE
{unsigned int code1: 2;unsigned int cdde2: 2;unsigned int code3: 8;
};
struct _PRCODE prcode;
该定义使prcode包含 2 个 2 Bits 位域和 1 个 8 Bits 位域,我们可以使用结构体的成员运算符对其进行赋值
prcode.code1 = 0;
prcode.code2 = 3;
procde.code3 = 102;
赋值时要注意值的大小不能超过位域成员的容量,例如 prcode.code3 为 8 Bits 的位域成员,其容量为 2^8 = 256,即赋值范围应为 [0,255]。
2、位域的大小和对齐
位域的大小
struct box
{unsigned int a: 1;unsigned int : 3;unsigned int b: 4;
};
该位域结构体中间有一个未命名的位域,占据 3 Bits,仅起填充作用,并无实际意义。 填充使得该结构总共使用了 8 Bits。但 C 语言使用 unsigned int 作为位域的基本单位,即使一个结构的唯一成员为 1 Bit 的位域,该结构大小也和一个 unsigned int 大小相同。 有些系统中,unsigned int 为 16 Bits,在 x86 系统中为 32 Bits。文章以下均默认 unsigned int 为 32 Bits。
位域的对齐
一个位域成员不允许跨越两个 unsigned int 的边界,如果成员声明的总位数超过了一个 unsigned int 的大小, 那么编辑器会自动移位位域成员,使其按照 unsigned int 的边界对齐。 例如:
struct stuff
{unsigned int field1: 30;unsigned int field2: 4;unsigned int field3: 3;
};
field1
+ field2
= 34 Bits,超出 32 Bits, 编译器会将field2
移位至下一个 unsigned int 单元存放, stuff.field1 和 stuff.field2 之间会留下一个 2 Bits 的空隙, stuff.field3 紧跟在 stuff.field2 之后,该结构现在大小为 2 * 32 = 64 Bits。
这个空洞可以用之前提到的未命名的位域成员填充,我们也可以使用一个宽度为 0 的未命名位域成员令下一位域成员与下一个整数对齐。 例如:
struct stuff
{unsigned int field1: 30;unsigned int : 2;unsigned int field2: 4;unsigned int : 0;unsigned int field3: 3;
};
这里 stuff.field1 与 stuff.field2 之间有一个 2 Bits 的空隙,stuff.field3 则存储在下一个 unsigned int 中,该结构现在大小为 3 * 32 = 96 Bits。
3、位域的初始化和位的重映射
初始化
位域的初始化与普通结构体初始化的方法相同,这里列举两种,如下:
struct stuff s1= {20,8,6};
或者直接为位域成员赋值
struct stuff s1;
s1.field1 = 20;
s1.field2 = 8;
s1.field3 = 4;
位域的重映射(re-mapping)
声明一个 大小为 32 Bits 的位域
struct box {unsigned int ready: 2;unsigned int error: 2;unsigned int command: 4;unsigned int sector_no: 24;
}b1;
利用重映射将位域归零
int* p = (int *) &b1; // 将 "位域结构体的地址" 映射至 "整形(int*) 的地址"
*p = 0; // 清除 s1,将各成员归零
利用联合 (union) 将 32 Bits 位域 重映射至 unsigned int 型
“联合” 是一种特殊的类,也是一种构造类型的数据结构。在一个 “联合” 内可以定义多种不同的数据类型, 一个被说明为该 “联合” 类型的变量中,允许装入该 “联合” 所定义的任何一种数据,这些数据共享同一段内存,以达到节省空间的目的。
“联合” 与 “结构” 有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和(空结构除外,同时不考虑边界调整)。而在 “联合” 中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。
我们可以声明以下联合:
union u_box {struct box st_box; unsigned int ui_box;
};
x86 系统中 unsigned int 和 box 都为 32 Bits, 通过该联合使 st_box 和 ui_box 共享一块内存。具体位域中哪一位与 unsigned int 哪一位相对应,取决于编译器和硬件。 利用联合将位域归零,代码如下:
union u_box u;
u.ui_box = 0;
学习笔记来自----------------------CPlusPlusThings/basic_content/bit at master · Light-City/CPlusPlusThings (github.com)
C++ bit field 位域/位段相关推荐
- (转)C结构体之位域(位段)
转载自C结构体之位域(位段) 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简 ...
- 聊一聊C语言位域/位段
目录 1.概念和定义 2.实例 在做嵌入式开发的时候,我们经常会遇到这样的代码: struct {unsigned int widthValidated : 1;unsigned int height ...
- 枚举的定义和使用,位域相关知识
1. 枚举类型:即列举 枚举类型的特点: (1) 枚举类型是一个受到限制的有符号的类型: (2)枚举值(元素)必须是整型值(有符号)://char 类型可以是'A',short类型可以,不允许字符串& ...
- 常见.Net 英文专业词汇收集
转自:http://www.ninedns.com/asp.net/2007102514949.html abstract class 抽象类 accelerator 快捷键 accele ...
- c语言prime函数怎么用_C语言教程_v20201106
编程基础 1.1 通俗地理解什么是编程语言 1.2 C语言究竟是一门怎样的语言? 1.6 初中毕业能学会编程吗? 1.7 C和C++到底有什么关系? 1.8 学了 C 语 ...
- 在c语言程序中可把整型数,C语言程序设计(2).doc
作业4 单项选择题 第1题 若要说明一个类型名STP,使得是定义语句STP s;等价于char *s;以下选项中正确的: A.typedef STP char *s; B.typedef *char ...
- 谭浩强c语言不讲位运算呢,谭浩强C语言教程第十二章-位运算.doc
谭浩强C语言教程第十二章-位运算 12位运算1 12.1位运算符C语言提供了六种位运算符:1 12.1.1按位与运算1 12.1.2按位或运算2 12.1.3按位异或运算2 12.1.4求反运算3 1 ...
- c++ 原子操作 赋值_请问c++如何实现原子性操作?
原子性,也就是要么全部做完,要么全部不做 在多进程(线程)访问资源时,能够确保所有其他的进程(线程)都不在同一时间内访问相同的资源.原子操作(atomic operation)是不需要同步,这是Jav ...
- c语言程序设计新编教程答案钱雪忠,新编C语言程序设计教程
图书简介 配套资源:电子课件.习题解答.源代码 本书特色: ★精选例题,引入了大量趣味性.游戏性应用实例,注重与加强程序阅读.参考.编写和上机调试实践的能力,重在编程思路的培养与训练. ★概念清晰但不 ...
最新文章
- 20145101《Java程序设计》第4周学习总结
- k-NN最近邻算法(k-nearest neighbors algorithm)
- Linux 自动重启进程
- Unable to locate package update
- Css网格布局-Grid布局
- config.cfg.php,PHP:使用给定的结构获取变量形式的config.cfg
- RabbitMQ 手动签收
- 作者:黄宜华,南京大学计算机系教授、博士生导师,中国计算机学会大数据专家委员会委员、副秘书长。...
- redis分布式锁,面试官请随便问,我都会
- keil5建立工程步骤_5个步骤建立实践社区
- CUDA Fortran for Scientists and Engineers第二版翻译
- JDK,JRE,JVM区别与联系(ZZ)
- com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
- 脑电EEG代码开源分享 【1.前置准备-静息态篇】
- 传送带计数器c语言程序,脉搏计数器的程序(用C语言编写程序)
- Linux移植Windows摄像头驱动,Arm-Linux摄像头驱动程序的移植
- php仿信用卡积分商城,中信银行信用卡积分购物商城
- 中央广播电视大学中等专业办公设备使用与维护
- 工业相机的镜头接口知识介绍
- 计算机视觉和模式识别的code