转载自C结构体之位域(位段)


有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有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 A5 {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 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简便,C ...

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

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

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

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

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

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

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

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

  6. c 结构体之位域(位段)

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

  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. Windows Server AppFabric Caching
  2. 计算机对应的自然科学,计算机类书稿加工应注意的几个问题
  3. 一个平庸程序员的自白
  4. Hinton神经网络公开课编程练习3 Optimization and generalization
  5. 点云处理软件Pointscene
  6. cmd mysql log_如何使用mysqlbinlog工具?
  7. model 提交表信息java,Angular6+antd+java+SpringMVC,表单提交自动接收模型对象?
  8. 未封装的扩展程序是什么意思_“冰壶见底未为清,少年如玉有诗名”这句诗是什么意思?...
  9. 官宣!VS Code Python 全新功能全球首发!
  10. html设置桌面背景win7,win7系统设置默认桌面背景的还原方案
  11. ElasticSearch入门手册
  12. 安装配置Axis2,为Eclipse安装配置Axis2插件教程
  13. Windows Server 2008 R2 C盘空间不足解决方法
  14. MS5611气压计数据采集(模拟IIC)/温度采集/相对高度求解
  15. 利用qiime2分析微生物组16S rRNA数据小结
  16. Java软件测试工程师之学习进阶路线
  17. Mac 关闭 Adobe Creative Cloud
  18. 【小白笔记】目标跟踪Deep Regression Tracking with Shrinkage Loss
  19. 《小狗钱钱》良句收录和读后感想
  20. HTML/HTML5

热门文章

  1. float foo=42e1为什么错_为什么重写了equals()也要重写hashCode()
  2. Hi3520d uImage制作 uboot制作 rootfs制作
  3. Python的threading多线程
  4. mac:在当前文件夹打开terminal终端
  5. [oralce] 利用CRT的端口转发功能直接用plsql访问数据库
  6. [react-router] React-Router 4怎样在路由变化时重新渲染同一个组件?
  7. [html] H5如何与APP交互?有哪些方式?
  8. [css] 你有用过哪些css框架?说说它们的特点
  9. 前端学习(2591):刷新页面vuex消失
  10. 前端学习(2502):vue指令v-if