自己如何做棋牌网站,设计制作网站板面,上海自贸区注册公司,东莞建筑公司位域位域是指信息在保存时#xff0c;并不需要占用一个完整的字节#xff0c;而只需要占几个或一个二进制位。为了节省空间#xff0c;C语言提供了一种数据结构#xff0c;叫“位域”或“位段”。“位域“是把一个字节中的二进位划分为几个不同的区域#xff0c;并说明每个… 位域位域是指信息在保存时并不需要占用一个完整的字节而只需要占几个或一个二进制位。为了节省空间C语言提供了一种数据结构叫“位域”或“位段”。“位域“是把一个字节中的二进位划分为几个不同的区域并说明每个区域的位数每个域有一个域名允许在程序中按位域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。位域的使用和结构成员的使用相同其一般形式为位域 变量名.位域名 位域允许用各种格式输出。1. 在C中位域可以写成这样注位域的数据类型一律用无符号的纪律性。struct bitmap
{unsigned a : 1;unsigned b : 3;unsigned c : 4;
}bit;sizeof(bitmap) 4;整个struct的大小为4因为位域本质上是从一个数据类型分出来的在我们的例子中数据类型就是unsigned大小为4并且位域也是满足C 的结构体内存对齐原则的等下我们会说到。2. 当然了位域也可以有空域。struct bitmap{unsigned a:4;unsigned :0; /*空域*/unsigned b:4; /*从下一单元开始存放*/unsigned c:4;}sizeof(bitmap) 8;
3. 在这个位域定义中a占第一字节的4位后4位填0表示不使用b从第二字节开始占用4位c占用4位。这里我们可以看到空域的作用是填充数据类型的剩下的位置有时候我们只是想调整一下内存分配则我们可以使用无名位域 struct bitmap {unsigned a:1;unsigned :2;unsigned b:3;unsigned c:2;};sizeof(bitmap) 4;
4. 如果一个位域的位的分配超过了该类型的位的总数则从下一个单元开始继续分配
这个很好理解struct bitmap{unsigned a : 8;unsigned b : 30;unsigned c : 4;};sizeof(bitmap) 12;注意这个位域的大小是12而不是8说明如果超了大小是立马从下一个单元开始分配。位域的使用主要出现在如下两种情况: (1)当机器可用内存空间较少而使用位域可以大量节省内存时。如,当把结构作为大数组的元素时。 (2)当需要把一结构或联合映射成某预定的组织结构时。例如,当需要访问字节内的特定位时。当要把某个成员说明成位域时,其类型只能是int,unsigned int与signed int三者之一(说明:int类型通常代表特定机器中整数的自然长度。short类型通常为16位,long类型通常为32位,int类型可以为16位或32位.各编译器可以根据硬件特性自主选择合适的类型长度.关于位域还需要提醒读者注意如下几点:其一,位域的长度不能大于int对象所占用的字位数.例如,若int对象占用16位,则如下位域说明是错误的: unsigned int x:17;其二,由于位域的实现会因编译程序的不同而不同,在此使用位域会影响程序的可移植性,在不是非要使用位域不可时最好不要使用位域.其三,尽管使用位域可以节省内存空间,但却增加了处理时间,在为当访问各个位域成员时需要把位域从它所在的字中分解出来或反过来把一值压缩存到位域所在的字位中.其四,位域的位置不能访问,因些不能对位域使用地址运算符号(而对非位域成员则可以使用该运算符).从而,即不能使用指向位域的旨针也不能使用位域的数组(因为数组实际上就是一种特殊的指针).另外,位域也不能作为函数返回的结果.最后还要强调一遍:位域又叫位段(位字段),是一种特殊的结构成员或联合成员(即只能用在结构或联合中).内存对齐1. 说到位域就不得说下内存对齐的东西其实内存对齐也很简单只是不同的编译器实现不一样至于为什么要内存对齐这个要从CPU的基本工作原理说起但是首先要明白无论我们是否内存对齐CPU大多数情况都是能正常工作的前提对于大多数IA32指令都可以这么说但是部分指令如SSE多媒体指令这些就不行这些指令有特殊内存对齐要求比如16字节对齐任何不满足内存对齐的地址访问储存器都是会导致异常对于这些指令编译器必须在编译的时候采取强制内存对齐。 实现内存对齐可以提高CPU的性能比如处理器能一次取出8个字节这个时候必须要求数据地址要8字节对齐这个是和CPU和储存器的外围电路决定的在内存对齐的情况下CPU从储存器取出这8个字节只需要一个时钟周期但是如果这个地址不是8字节对齐那么CPU可能就需要两个时钟周期才能取出这8个字节。 对于IA32每个栈帧都惯例16字节对齐编译器一般也会那么做但是对于数据类型不同的编译器表现可能不一样对于WindowsVC编译器任何K字节的基本对象的地址都必须是K的倍数比如对于int必须4字节对齐对于double必须8字节对齐这很大程度上提高了储存器和CPU的工作性能但是对存储空间的浪费比较严重对于Linux惯例是8字节数对齐4字节边界比如double可以4字节对齐。对于Windows好Linux数据类型long double都有4字节对其的要求对于GCClong double分配12字节虽然它只占10字节大小。 所以我们有一般规则struct X
{char a; float b; int c; double d; unsigned e;
};
sizeof(X) 32;内存对齐状况应该是下面这个样子struct X
{char a; // 1 bytes char padding1[3]; // 3 bytes float b; // 4 bytes int c; // 4 bytes char padding2[4]; // 4 bytes double d; // 8 bytes unsigned e; // 4 bytes char padding3[4]; // 4 bytes};
sizeof(X) 32;其中最后的4个字节的填充是因为规则4看下面。2. 如果自定义数据类型含有位域则内存对齐满足以下原则 1. 如果相邻的位域的数据类型相同则按照分配位的大小来详情看我上面写的位域的第5个情况。 2. 如果相邻的位域的数据类型不相同则不同编译器实现不一样有些编译器选择不压缩。 3. 如果位域不连续中间含非位域则按标准数据类型大小划分比如struct bitmap
{unsigned a : 2; int b; unsigned c : 3;
};
sizeof(bitmap) 12;
3. 另外可以通过添加#pragma pack(n)来强制改变内存分配情况比如在VC编译器中
struct bitmap{unsigned a;double c;};sizeof(bitmap) 16;加了#pragma pack(4)则强制内存对齐4字节再测试下其大小#pragma pack(4)
struct bitmap
{unsigned a; double c;
};
sizeof(bitmap) 12;当然如果#pragma pack(n)的n大于本身数据类型的宽度则按数据类型的宽度来分配struct bitmap
{double c; int k; int m;
};
sizeof(bitmap) 16 32
4. 自定义类型C结构体C聚合类的最后的内存对齐是按照自定义类型内的最大类型的宽度来的比如上面那个例子去掉int m
struct bitmap{double c;int k;};
sizeof(bitmap) 16必须以double进行8字节对齐VC编译器。声明本文于网络整理版权归原作者所有如来源信息有误或侵犯权益请联系我们删除或授权事宜。