位域操作

看runtime源码时,看到如下声明变量的,变量后分号前加冒号和数字": 数字"即为位域操作。

uintptr_t indexed           : 1;

 

1个字节包含8位,有些变量保存的数据不需要占用这么长的空间(比如bool类型,只有两个状态true和false, 1位就可以搞定,剩下的7位就浪费了),这就催生了“位域”结构,位域将1个字节划分成不同的区域,每个区域都有个位域名(可以理解为变量名,上边的代码中位域名为indexed),程序员可以代码通过位域名访问其中的数据。

 

一. 声明

 
类型说明符 位域名:位域长度;
 

 

位域结构体,我理解是一种特殊的结构体,其成员变量都是位域,声明如下

 

struct 位域结构名 
{
  类型说明符 位域名:位域长度;
  类型说明符 位域名:位域长度;
  类型说明符 位域名:位域长度;
  ...
  类型说明符 位域名:位域长度;
};

  

二. 基本原则

1. 位域变量的长度不能大于其类型的长度(sizeof(类型) * 8)

变量char has_assoc的类型位char 1字节 8位,小于定义的10,所以编译器警告

 

2.  不能用于位域字段的操作:取地址操作符&,取偏移量操作

位域是若干位空间,是没有地址的

 

 

3. 位域可以是无名位域,无名位域只能用作填充或调整位置,不能使用。如下图结构体S007的最后一个变量就是无名位域,无法使用

 

4. 位域字段不能声明为类的静态成员

 

5. 位域结构体的大小必须是其最长基本类型大小的整数倍(sizeof(类型) * 8)

 

三. 内存分配规则

1. 判断大小端,以我自己的机子为例,不同环境下有可能不同

 

定义联合体U007和位域结构体S007,将U007实例u7的number赋值31,二进制为 | 0000 0000 | 0000 0000 | 0000 0000 | 0001 1111 |,根据存储原则,数值都是从高地址往低地址读,因此位域结构体S007中的位域变量是从低地址开始分配内存的,即

 

2. 位域变量类型相同

位域变量长度之和小于[sizeof(变量类型)*8], 则后面的位域字段将紧邻前一个字段存储, 直到不能容纳为止

位域变量长度之和大于[sizeof(变量类型)*8], 则后面的位域字段将从下一个存储单元的起始地址处开始存放(其偏移量恰好为sizeof(变量类型)的整数倍)

 

位域结构体S007的3个成员变量都是unfigned short类型,sizeof(unfigned short)*8 = 16位,

a0占1位,从起始地址分配1位;

a1占9位,a0+a1=10位,小于16位(sizeof(unfigned short)*8),因此a1在a0后连续分配9位;

a2占15位,(a0 + a1) + a2 = 25位,大于16位,因此跳过6位,在S007起始地址偏移量为16位的地方,给a2分配15位。

再次提醒:小端是分配内存地址时从低地址开始,但是变量的数值是从高地址往低地址读

 

3. 位域变量类型不同时,各个编译器的具体实现有差异,VC6采取不压缩方式,GCC和Dev-C++都采用压缩方式,以下是我自己机子的处理方式

 

位域结构体S007的前2个成员变量unfigned char类型(sizeof(unfigned char)*8 = 8位),后一个成员变量unfigned short(sizeof(unfigned short)*8 = 16位)

 

a占2位,从起始地址分配2位;

b占3位,a+b=5位,小于8位(sizeof(unfigned char)*8,b的类型是unfigned char),因此b在a后连续分配3位;

c占15位,(a + b) + c = 20位,大于16位(sizeof(unfigned short)*8,c的类型是unfigned short),因此跳过11位,在S007起始地址偏移量为16位的地方,给c分配15位。

 

有上图可以看出,在我的机子上,如果位域变量的类型不同,仍会进行内存压缩(如果需要跳位,判断哪个位域变量,就用该变量的类型进行偏移量对齐判断)

 

 4. 如果位域变量之间穿插着非位域变量, 则不进行压缩

非位域变量也可以理解为特殊的位域变量,只不过占的位数是变量长度,即 类型 位域名 : sizeof(类型)*8

根据规则3,则无法进行内存压缩

 

位域结构体S007的第2个成员变量char tmp;是非位域变量,转成位域变量为 char tmp:8;

 

a占2位,从起始地址分配2位;

tmp占8位,a+tmp=10位,大于8位(sizeof(char)*8,tmp的类型是char),因此跳过6位,在S007起始地址偏移量为8位的地方,给tmp分配8位;

b占3位,在tmp后给b分配3位。

 

 

5. 上边举的例子中参数都是unsigned标识的,如果带上符号位会是什么情况呢?

关于带符号基本类型变量在内存中存储方式,请看这里http://www.cnblogs.com/xieyajie/p/8125214.html

 

位域结构体S008定义了2个带符号位域变量,a0占2位,a1占3位

a0是带符号short类型,内存中保存的是补码11,首位符号位为1,负数,推出源码为11,转为十进制为-1;

a1是带符号short类型,内存中保存的是补码001,首位符号位为0,正数,源码为001,转为十进制为1。

 

如果a0只占1位会怎么样?从测试结果可以看出,这1位几十符号位,也是数值位

转载于:https://www.cnblogs.com/xieyajie/p/8110224.html

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

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

相关文章

工作211:新的封装组件 秒呀

<!-- 可以动态新增的 tag 列表 --> <template><div><el-tagv-for"(tag, index) in dynamicTags":key"index":closable"true":disable-transitions"false"close"handleClose(tag)">{{ tag }}</el…

HTTP协议简介,数据安全 如何保证http传输安全性,http与https区别

目前大多数网站和app的接口都是采用http协议&#xff0c;但是http协议很容易就通过抓包工具监听到内容&#xff0c;甚至可以篡改内容&#xff0c;为了保证数据不被别人看到和修改&#xff0c;可以通过以下几个方面避免。 重要的数据&#xff0c;要加密&#xff0c;比如用户名密…

mongoose只更新数组中某一项的字段

只是需要一个特殊符号$代表匹配某一项 数据库设计如下&#xff1a; 核心代码如下&#xff1a; // 回答试题public async userPaperAnswer(request: IRequest, _h: IResponse) {const { user_paper_id, question_id, option_user } request.payload;const updOne await Use…

工作213:不能改变父组件值

父组件通过props传值给子组件&#xff0c;如何避免子组件改变props的属性值报错问题 报错Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s v…

Android 下拉式抽屉折叠动画

自定义listview工具类1、 public class ViewMeasureUtils {/*** 根据父 View 规则和子 View 的 LayoutParams&#xff0c;计算子类的宽度(width)测量规则** param view*/public static int getChildWidthMeasureSpec(View view, int parentWidthMeasureSpec) {// 获取父 View …

beta冲刺总结

团队成员及分工 姓名学号分工陈家权031502107前端&#xff08;消息模块&#xff09;赖晓连031502118前端&#xff08;问答模块&#xff09;雷晶031502119服务器林巧娜031502125前端&#xff08;首页模块&#xff09;一、项目预期计划及现实进展 项目预期计划现实进展解决页面异…

cesium polygon 悬浮在半空中

效果如下&#xff1a; 代码&#xff1a; let arr [[120.87140893447473, 31.877030830389447, 128.64],[120.87140872335587, 31.876963534304792, 128.64],[120.87202301763111, 31.87696299560446, 128.63],[120.87202432001283, 31.877030271988385, 128.63]]arr [].con…

工作215:点击按钮报错

获取值有点问题 点击同一按钮获取值有问题

phalcon无限重定向

问题 换了个新电脑&#xff0c;后来重新配置phalcon环境。由于用得是windows&#xff0c;而且还用得是2.0.5得版本&#xff0c;官网已经没提供这个版本下载了。而旧电脑已经被格式化了&#xff0c;?。 寻找旧版本 通过一番搜索&#xff0c;发现了一个issue&#xff0c;提到pha…

!KMP算法完整教程

KMP算法完整教程 全称: Knuth_Morris_Pratt Algorithm(KMP算法) 类型: 高级检索算法 功能: 字符串匹配查找 提出者: D.E.Knuth(克努兹),J.H.Morris(莫瑞…

修改git bash主题配色和字体

这win下默认的主题令人窒息 打开git bash&#xff0c;使用命令cd ~然后用Atom命令打开文件.minttyrc.atom .minttyrc如果默认没有.minttyrc文件&#xff0c;自己新创建的也行。里面的内容填写如下&#xff1a;FontConsolas FontHeight14ForegroundColour131,148,150 Background…

jdk和maven配置

Java 1、首先准备一下文件 2、直接安装jdk&#xff0c;我是一直下一步&#xff0c;路径也是默认 3、开始配置环境变量 电脑--属性--高级--环境变量&#xff0c;新建系统变量 JAVA_HOME 和 CLASSPATH变量名&#xff1a;JAVA_HOME变量值&#xff1a;C:\Program Files\Java\…

java 数据结构详解,数组,集合,HashMap

数组的特性&#xff1a; 数组在内存中是一块连续的存储单元存储起来的&#xff0c;声明数组的时候我们必须声明其长度&#xff0c;这样才会为我们声明一个连续的存储区域。 这种存储方式造成我们想要往数组中存储一个数据时那么其后面各个元素都要往后移动&#xff0c;同样的&…

工作218:页面样式调整

<div class"table-list-page"><div class"query-area"><!--样式控制全部 已经退回 待审核GY--><el-row><el-radio-group v-model"query.status" change"list"><el-radio-button label""&g…

前端学习(2681):重读vue电商网站1之后台启动

后台数据接口启动文件 node -app.js 需要mysql数据库

Promise初步详解(resolve,reject,catch)

一:何为Promise&#xff1f; 为了直观一点&#xff0c;首先我们采用console.dir(Promise)看一下它的结构组成。 从上面的图片中我们可以到&#xff0c;Promise其实是一个构造函数&#xff0c;它有resolve&#xff0c;reject&#xff0c;race等静态方法;它的原型&#xff08;pro…

session 的 源码

session 的 源码 1.session 和 cookie 的 区别&#xff1a; 答&#xff1a; cookie 它是保存在浏览器的键值对。 session 它是保存在服务端的键值对。 它 依赖cookie 存在。 流程&#xff1a; 一个服务端&#xff0c; 一个客户端第一次来 服务端 去 客户端 发来的请求里的…

前端学习(2682):重读vue电商网站3之登录页面总结el-form 组件问题

el-form 组件默认是 content-box&#xff0c;我们设置其如下属性时&#xff0c;就会出现长度比我们想象中长一点的情况。 .login_form {position: absolute;bottom: 60px;width: 100%;padding: 0 20px; //多加一行box-sizing: border-box; } 运行结果