位域操作

看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…

Koa2+Mysql搭建简易博客

http://blog.csdn.net/wclimb/article/details/77890793 转载于:https://www.cnblogs.com/SharkChilli/p/8177753.html

工作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…

uniapp移动H5在花生壳Invalid Host header

解决方案&#xff0c;在manifest.json中配置 "h5" : {"title" : "","domain" : "","devServer" : {"disableHostCheck" : true} }

Android 下拉式抽屉折叠动画

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

18.抽象模板方法———获取程序运行的时间

需求&#xff1a;获取一段程序运行的时间。原理&#xff1a;   获取程序开始和结束的额时间并相见即可  获取时间&#xff1a;System.currentTimeMillis(); 当代码完成优化后&#xff0c;就可以解决这类问题。这种方式&#xff0c;叫模板方法设计模式。 什么是模板方法呢&a…

js随机从数组中取出几个元素

这篇文章为转载&#xff0c;我的需求是从题库中&#xff0c;随机抽几道题&#xff0c;作为新试卷。代码如下&#xff1a; var items [1,2,4,5,6,7,8,9,10];1.从数组items中随机取出一个元素 var item items[Math.floor(Math.random()*items.length)];2.从前面的一篇随机数组…

工作214:结构 vue操作一个很有意思的报错 [Vue warn]: You may have an infinite update loop in a component

结构 vue操作一个很有意思的报错 [Vue warn]: You may have an infinite update loop in a component render function. 代码&#xff1a; <template><span class"show-filters" &#xff1a;class"show !show">{{ show ? 隐藏过滤器 ↑ …

Android 实现选中与非选中样式效果

drawable文件 <?xml version"1.0" encoding"utf-8"?> <selector xmlns:android"http://schemas.android.com/apk/res/android"><item android:drawable"drawable/log_button_bgok" android:state_focused"true&…

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…

工作按钮(216):点击按钮报错--bug修复--直接写接口里面

this.title "编辑";getAction(path.join(this.url.query, id)).then(res > {this.form res.data;}).catch(err > {this.form JSON.parse(JSON.stringify(this.defaultForm));this.$message.warning("获取数据失败&#xff01;");}).finally(() &g…

cesium billboard 设置距离控制可见度

核心代码如下 viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),billboard: {image: /imgs/disease/1.png,scaleByDistance

!KMP算法完整教程

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

windows安装nvm

最近mac电脑坏了&#xff0c;需要送修&#xff0c;暂时切换到windows平台进行开发。 下面安装nvm。 先保证电脑没有安装node github下载地址&#xff1a; https://github.com/coreybutler/nvm-windows/releases 找到nvm-setup.zip 下载解压安装即可。 我都是使用的默认安…