有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:

struct 位域结构名
{位域列表};

其中位域列表的形式为:

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

位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如:

struct bs
{int a:8;int b:2;int c:6;
}data; 

说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明:

1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:

struct bs
{unsigned a:4unsigned b:5 /*从下一单元开始存放*/unsigned c:4
}

2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度。

3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

struct k
{int a:1int :2 /*无位域名,该2位不能使用*/int b:3int c:2
}; 

二、位域的使用

下面例子是参加一个公司(白领科技-青岛)的笔试遇到的,当时做错了,为了怕忘了,赶紧写下来。

 1 #include <iostream>
 2 #include <memory.h>
 3 using namespace std;
 4 struct A
 5 {
 6     int a:5;
 7     int b:3;
 8 };
 9 int main(void)
10 {
11     char str[100] = "0134324324afsadfsdlfjlsdjfl";
12         struct A d;
13     memcpy(&d, str, sizeof(A));
14     cout << d.a << endl;
15     cout << d.b << endl;
16     return 0;
17 }

在32位x86机器上输出:

$ ./langxun.exe
-16
1

解析:在默认情况下,为了方便对结构体内元素的访问和管理,当结构体内的元素长度都小于处理器的位数的时候,便以结构体里面最长的元素为对其单位,即结构体的长度一定是最长的数据元素的整数倍;如果有结构体内存长度大于处理器位数的元素,那么就以处理器的位数为对齐单元。由于是32位处理器,而且结构体中a和b元素类型均为int(也是4个字节),所以结构体的A占用内存为4个字节。

上例程序中定义了位域结构A,两个个位域为a(占用5位),b(占用3位),所以a和b总共占用了结构A一个字节(低位的一个字节)。

当程序运行到14行时,d内存分配情况:

 高位 00110100 00110011   00110001    00110000 低位       '4'       '3'       '1'          '0'   其中d.a和d.b占用d低位一个字节(00110000),d.a : 10000, d.b : 001

d.a内存中二进制表示为10000,由于d.a为有符号的整型变量,输出时要对符号位进行扩展,所以结果为-16(二进制为11111111111111111111111111110000)

d.b内存中二进制表示为001,由于d.b为有符号的整型变量,输出时要对符号位进行扩展,所以结果为1(二进制为00000000000000000000000000000001)

三、位域的对齐

  如果结构体中含有位域(bit-field),那么VC中准则是:

  1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;

  2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

  3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采取压缩方式;

  系统会先为结构体成员按照对齐方式分配空间和填塞(padding),然后对变量进行位域操作。

c 结构体之位域(位段)相关推荐

  1. (转)C结构体之位域(位段)

    转载自C结构体之位域(位段) 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简 ...

  2. C结构体之位域(位段)

    C结构体之位域(位段) 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简便,C ...

  3. 结构体之位域(位段)

    结构体之位域(位段) 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简便,C语 ...

  4. 结构体之位域全面分析

    结构体的定义 typedef struct TEST {... }Test,*pTest;struct TEST {... }test 这里的test是一个TEST变量.. 结构体之位域 有些信息在存 ...

  5. C语言结构体中的位段

    C语言结构体中的位段 位段的内存分配 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型 位段的空间上是按照需要以4个字节( int )或 ...

  6. 结构体 + 联合体 + 位域 使用

    简单介绍结构体 定义结构体,一般是对有相同属性的元素或成员的归纳,比如电机的电气特性:驱动电压.驱动电流.运行速度:还有比如系统报警类:过压报警.过流报警.欠压报警 本人常用格式 typedef  s ...

  7. 在C语言中各种数据类型各占多少位 C语言 中结构体的位域(位段)

    (一)32位平台: 分为有符号型与无符号型. 有符号型: short 在内存中占两个字节,范围为-2^15~(2^15-1) int 在内存中占四个字节,范围为-2^31~(2^31-1) long在 ...

  8. C语言中结构体的位域(bit-fields)

    有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可.例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位.正是基于这种考虑,C语言又提供了一种叫做位域 ...

  9. C 语言编程 — 高级数据类型 — 结构体与位域

    目录 文章目录 目录 前文列表 结构体 定义结构体 初始化结构体变量 访问结构体成员 结构体的内存分布 将结构体作为实参传入函数 指向结构体变量的指针 位域 定义位域 使用位域结构体的成员 前文列表 ...

最新文章

  1. codeforce 1311 C. Perform the Combo 前缀和
  2. 降本增效利器!趣头条Spark Remote Shuffle Service最佳实践
  3. Java常用设计模式————桥接模式
  4. SpringBoot集成MyBatis-Plus框架详细方法
  5. php 实现二叉树的最大深度_python实现二叉树的遍历以及其他基本操作
  6. 路由器用到坏才换?路由器你在乎哪些功能?
  7. Windows同步对象Event和Linux的条件变量
  8. php 内存池,内存详解: 详解PHP内存池中的存储层_php
  9. 机器学习常见数据集下载(免费)
  10. 解决 ZeroDivisionError integer division or modulo by zero
  11. Golang 获取月初和月底日期
  12. Android 仿微信回复评论点赞效果
  13. XSS原理dvwaxssvalidator使用
  14. 抽卡模拟系统(包含图形界面,结果可存储到数据库中)
  15. 3D真人手办,做一个迷你版的自己
  16. 冷池机房给数据中心带来哪些好处
  17. (8.1.5.4)Android Testing Support Library翻译之Espresso 备忘录
  18. 世界上最远的距离------泰戈尔
  19. STC-ISP的定时器计算器初值计算
  20. linux 伪静态 cms,YzmCMS伪静态配置

热门文章

  1. python程序语法元素的描述_Python入门——Python程序语法元素
  2. .rpt文件内容读取java_python读取PDF指定表格内容批量文件重命名
  3. python中for循环的用法_@Python小白,一文让你掌握Python爬虫
  4. c#调用c++ dll const char* String类型转换问题。传值,与接收返回值问题
  5. MySQL 跨版本主从复制时报错:ERROR 1794 (HY000): Slave is not configured or failed to initialize properly....
  6. MySQL教程(二)—— 关于在ACCESS中使用SQL语句
  7. 调试程序Bug-陈棚
  8. 前端笔试题【1】--从字符串的第二个字符开始对数组进行排序
  9. hdu 1171 dp(多重背包)
  10. LeetCode(226)——翻转二叉树(JavaScript)