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

转载自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),然后对变量进行位域操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/409020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java为何重复调用方法_通过反射调用Java中的getter:重复调用它的最快方法是什么(在性能和可伸缩性方面)?...

小编典典您可以使用MethodHandle。其Javadoc写道&#xff1a;使用Lookup API中的工厂方法&#xff0c;可以将Core ReflectionAPI对象表示的任何类成员转换为行为等效的方法句柄。例如&#xff0c;可以使用Lookup.unreflect将反射方法转换为方法句柄。生成的方法句柄通常提供对底…

表单提交中get 和post方式的区别

两者的区别需要通过提交表单后才看得出来&#xff0c;主要是在数据发送方式和接收方式上 1.在客户端&#xff0c;Get方式在通过URL提交数据&#xff0c;就是把表单内的元素&#xff0c;转化成url参数提交&#xff0c;比如你有一个页面index.html&#xff0c;这个页面有一个文本…

linux mysql5.7.11_在Linux中以命令行方式安装 MySQL 5.7.11 for Linux Generic 二进制版本

转至: http://www.cnblogs.com/cyberniuniu/p/5273961.htmlMySQL 目前的最新版本是 5.7.11&#xff0c;在 Linux 下提供特定发行版安装包(如 .rpm)以及二进制通用版安装包(.tar.gz)。一般情况下&#xff0c;很多项目都倾向于采用二进制通用安装包形式来进行安装配置&#xff0c…

论文阅读(2)--Picking Deep Filter Responses for Fine-grained Image Recognition

这次阅读的文章是Picking Deep Filter Responses for Fine-grained Image Recognition&#xff0c;这篇文章是来自上海交通大学Xiaopeng Zhang等人的工作&#xff0c;该文章提出了一种对深度网络中的filter进行挑选的方法&#xff0c;基于挑选的filter的结果构建复杂特征表达。…

vc2008使用技巧

开发程序自动以管理员的身份运行&#xff1a; 2008里面自带一个选项&#xff1a;属性-配置属性-连接器-清单文件-Uac执行级别&#xff0c;里面可以选转载于:https://www.cnblogs.com/fwycmengsoft/archive/2013/03/26/2982874.html

论文阅读(3)--SPDA-CNN: Unifying Semantic Part Detection and Abstraction for Fine-grained Recognition

这篇文章是来自罗格斯大学的Han Zhang等人的工作。由题目可知与上一篇文章一样&#xff0c;本文的作者也关注到了富有语义的局部(利用Part&#xff0c;Part&#xff0c;Part&#xff0c;重要事情强调三遍)&#xff0c;作者不满足于CUB-2011数据库提供的head和body的定位结果&am…

从流水中倒推算出销量为多某值的日期

SELECT rq,spid,chkshl, (SELECT SUM(chkshl) AS chkshl FROM spls_ck WHERE T.plh < plh and spidSPH00009425 having SUM(chkshl)<10 ) AS chkshl FROM spls_ck T where spidSPH00009425 order by plh desc 转载于:https://www.cnblogs.com/bingyuw/archive/2013/03/29…

egg.js java 生产数据_eggjs中,自动从数据库直接生成model.

eggjs中,自动从数据库直接生成model.使用sequelize-auto可以自动生成models直接上命令就可以搞定了# 安装必要的库npm install -g sequelize-auto# MySQL/MariaDB 数据库安装对应的库,其他数据库请看文档npm install -g mysql# 从命令行生成modelssequelize-auto -o ./database…

论文阅读(4)--Part-Stacked CNN for Fine-Grained Visual Categorization

这篇文章是来自悉尼科技大学Shaoli Huang等人的工作&#xff0c;与前两篇文章的出发点类似&#xff0c;本篇文章也是在Parts上寻找Fine-Grained的线索&#xff0c;但与前两篇文章相比&#xff0c;在框架中人工的参与更少。同其它Fine-Grained分类任务相似&#xff0c;这篇文章也…

java组件自适应窗口大小_java swing 窗口和控件自适应大小

本文记录java开发CS结构时怎么自适应屏幕大小以及控件跟随frame大小变化大小、位置和字体大小需要注意&#xff1a;1、代码必须放置在其构造方法中。如&#xff1a;我的frame1是我frame.java的名&#xff0c;则代码放置在方法“public Frame1() ”中。2、放在控件初始化后的地方…

剑指offer--二维数组的查找

记录《剑指offer》上的算法题。完整的代码例子可以在我的Github 题目&#xff1a;在一个二维数组中&#xff0c;每一行按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断…

仙元天下试玩感受

仙元天下是安讯网洛旗下的游戏&#xff0c;在官网注册账号的时候就遇到了问题&#xff0c;注册页面无法打开&#xff0c;服务器网址错误&#xff0c;只有返回到官网首页进行快捷注册。 画面2D&#xff0c;有自动打怪&#xff0c;画面感一般&#xff0c;反应比较迟钝&#xff0c…

剑指offer--替换空格

记录《剑指offer》上的算法题。完整的代码例子可以在我的Github。 这是一道有关字符串的问题。首先在C/C中&#xff0c;会把常量字符串放到单独的一个内存区域中&#xff0c;当几个指针赋值给相同的常量字符串时&#xff0c;它们实际上会指向相同的内存地址&#xff1b;但如果…

java打开word文件名乱码怎么解决_Word文档乱码怎么办?解决Word文档乱码的几种常见方法...

最近Word经常出现问题&#xff0c;双击打开后就弹出“文件转换”的对话框&#xff0c;让选择装载此文件时要使用的编码&#xff0c;选择了简体中文&#xff0c;打开文档后还是乱码&#xff0c;遇到这种情况我们应该怎么办呢?解决方法一&#xff1a;把原来的文档另存为*.rtf格式…