看runtime源码时,看到以下声明变量的,变量后分号前加冒号和数字": 数字"即为位域操做。html
uintptr_t indexed : 1;
1个字节包含8位,有些变量保存的数据不须要占用这么长的空间(好比bool类型,只有两个状态true和false, 1位就能够搞定,剩下的7位就浪费了),这就催生了“位域”结构,位域将1个字节划分红不一样的区域,每一个区域都有个位域名(能够理解为变量名,上边的代码中位域名为indexed),程序员能够代码经过位域名访问其中的数据。程序员
一. 声明测试
类型说明符 位域名:位域长度;
位域结构体,我理解是一种特殊的结构体,其成员变量都是位域,声明以下ui
struct 位域结构名 {
类型说明符 位域名:位域长度;
类型说明符 位域名:位域长度;
类型说明符 位域名:位域长度;
...
类型说明符 位域名:位域长度;
};
二. 基本原则spa
1. 位域变量的长度不能大于其类型的长度(sizeof(类型) * 8)code
变量char has_assoc的类型位char 1字节 8位,小于定义的10,因此编译器警告htm
2. 不能用于位域字段的操做:取地址操做符&,取偏移量操做blog
位域是若干位空间,是没有地址的内存
3. 位域能够是无名位域,无名位域只能用做填充或调整位置,不能使用。以下图结构体S007的最后一个变量就是无名位域,没法使用get
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位几十符号位,也是数值位