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

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

其中位域列表的形式为:

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

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

struct bs
{
  int a:;
  int b:;
  int c:;
}data;

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

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

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

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

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

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

二、位域的使用

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

#include <iostream>
#include <memory.h>
using namespace std;
struct A
{
int a:;
int b:;
};
int main(void)
{
char str[] = "0134324324afsadfsdlfjlsdjfl";
struct A d;
memcpy(&d, str, sizeof(A));
cout << d.a << endl;
cout << d.b << endl;
return ;
}

在32位x86机器上输出:

$ ./langxun.exe
-

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

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

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

高位          低位
'' '' '' ''
其中d.a和d.b占用d低位一个字节(),d.a : , d.b :

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结构体之位域(位段)

[转]C结构体之位域(位段)的更多相关文章

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

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

  2. C结构体中位域

    C结构体中位域的一点小知识,最近在看资料时遇到结构体中的一种特殊操作——位域,在下面的程序中我将根据自己的理解进行简单介绍.程序只是为了了解位域的一些性质,运行时有些编译器可能会报错. 程序代码如下( ...

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

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

  4. C 结构体、位域

    参考链接:https://www.runoob.com/cprogramming/c-structures.html 结构体是干啥的 例如数组可以用来存储多个相同数据类型的数据项,结构体也是一种数据类 ...

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

    转自:http://blog.sina.com.cn/s/blog_6240b5980100tcba.html 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一 ...

  6. 【转】C语言中结构体的位域(bit-fields)

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

  7. C语言结构体定义位域,从bit0开始,依次到最高bit位

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

  8. 全面总结sizeof的用法(定义、语法、指针变量、数组、结构体、类、联合体、位域位段)

    一.前言 编译环境是vs2010(32位). <span style="font-size:18px;">#include<iostream> #inclu ...

  9. 关于牛客网C语言结构体位域(bit-fields)的一道题

    题目链接地址: https://www.nowcoder.com/questionTerminal/f4e20747a2dd4649bac0c028daa234f4 来源:牛客网 低地址字节 Byte ...

随机推荐

  1. js静态数据分页展示

    拿vue做示例 首先定义data data() { return { tableData: [], // 当前页的数据,用于给表格展示用的 tableDataAll: [], // 需要拿来分页的总数 ...

  2. mysql 删除某一个数据库下面的所有表,但不删除数据库

    删除某一个数据库下面的所有表,但不删除数据库.该语句经过从concat拼接,最后查询出来的是删除表的语句,然后执行那些查询出来的语句就ok了select concat(‘drop table ‘,ta ...

  3. 在Eclipse中指定JDK

    1.Windows下的Eclipse中的eclipse.ini -startup plugins/org.eclipse.equinox.launcher_1.3.100.v20150511-1540 ...

  4. OpenGL学习--开发环境

    1. VS2017 Professional安装 1.1. 下载 mu_visual_studio_professional_2017_x86_x64_10049787.exe 1.2. 双击开始安装 ...

  5. AR中的SLAM(一)

    写在前面 本系列打算讲讲个人对AR行业和AR中的SLAM算法的一点浅显的看法.才疏学浅,文中必然有很多疏漏和不足,还望能和大家多多讨论.今天先讲讲我对AR的一些认识. AR的一点理解 AR是什么 AR ...

  6. XSS学习(未完..)

    前言 XSS 漏洞原理非常简单,实际应用中非常灵活,于是通过 prompt(1) to win 来学习学习 正文 工具 分析正则表达式 https://regex101.com/ http://xss ...

  7. 132.1.001 Union-Find | 并查集

    @(132 - ACM | 算法) Algorithm | Coursera - by Robert Sedgewick > Tip: Focus on WHAT is really impor ...

  8. 网络 OSI参考模型与TCP/IP模型

    ISO是国际标准化组织.OSI,开放互联系统.IOS,思科交换机和路由器的操作系统. TCP/IP模型是OSI模型的简化.所有的互联网协议都是基于OSI模型开发的. 分层:便于管理,每层只管理下层,总 ...

  9. 从零开始学习Docker

    由于项目中可能用到docker容器,在此记录一下我的学习过程 1,docker的安装,wget -qO- https://get.docker.com/ | sh,查看docker是否安装成功: 此处 ...

  10. 进程间协作---wait,notify,notifyAll

    转自牛客网的一篇评论,解释的十分详细 在 Java 中,可以通过配合调用 Object 对象的 wait() 方法和 notify()方法或 notifyAll() 方法来实现线程间的通信.在线程中调 ...