C++字节对齐与位域
环境:
win7_x64旗舰版、VS2015企业版
一、字节对齐:
说明:为了提高 CPU 的存储速度,编译器会对 struct 和 union的存储进行优化,即进行字节对齐。
1. 指定对齐参数值:通过#pragma pack(push, n)设置。
2. 自身对齐参数值:每个内部类型自身也都有一个对齐参数,一般来说这个对齐参数就是 sizeof(type) 的值,也就是char的自身对齐参数是1,short是2,int是4,float也是4,double是8等。
3. 有效对齐参数值:内部类型的有效对齐是指它的自身对齐参数和指定对齐参数中较小的那个值;
4. 结构体整体的有效对齐参数值:是指它的成员中,有效对齐参数最大的那个值。
例如:
///< 假设按4字节对齐
#pragma pack(push, 4)
struct data {
char a; //a的有效对齐参数值是min(1,4)为1字节,从第1字节开始,占1字节
char b; //b的有效对齐参数值是min(1,4)为1字节,从第2字节开始,占1字节
long long c; //d的有效对齐参数值是min(8,4)为4字节,从第5个字节开始,占8字节
short d; //e的有效对齐参数值是min(2,4)为2字节,从第13个字节开始,占2字节
};
它们的和为1字节(a)+1字节(b)+2字节(填充)+8字节(c)+2字节(d)=14字节。
因为整体结构体还需要进行对齐,结构成员最大有效对齐参数值为4,所以整个结构为4的整数倍,最后的总大小为4 * 4 = 16字节。
二、位域:
说明:C/C++中以一定区域内的位(bit)为单位来表示的数据成为位域,位域必须指明具体的数目,位域的作用主要是节省内存资源,使数据结构更紧凑。
1. 取地址操作符&不能应用在位域字段上;
2. 位域字段不能是类的静态成员;
3. 位域字段在内存中的位置是按照从低位向高位的顺序放置的;
4. 位域的对齐
a. 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
b. 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
c.如果相邻的两个位域字段的类型不同,则各个编译器的具体实现有差异,VC6采取不压缩方式,采用第一节说的字节对齐方式进行。
d. 整个结构体的总大小采用字节对齐方式的第4点。
e. 如果位域字段之间穿插着非位域字段,则不进行压缩,采用第一节说的字节对齐方式进行。
f. 无名的位域不能使用,只能用于填充,位宽为0表示强制下一位域对齐到当前类型的边界。
例如:
///< 假设按4字节对齐
#pragma pack(push, 4)
struct data {
short a : ; //从第1个字节开始,占1字节,使用7位
short b : ; //从第2个字节开始,占1字节,使用5位
long long e : ; //与上个类型不一致,e的有效对齐参数值是min(8,4)为4字节,所以从第5个字节开始,占8字节,使用4位
char f : ; //与上个类型不一致,f的有效对齐参数值是min(1,4)为1字节,所以从第13个字节开始,占1字节,使用1位
};
它们的和为1字节(a)+1字节(b)+2字节(填充)+8字节(e)+1字节(f)=13字节。
因为整体结构体还需要进行对齐,结构成员最大有效对齐参数值为4,所以整个结构为4的整数倍,最后的总大小为4 * 4 = 16字节。
///< 假设按4字节对齐
#pragma pack(push, 4)
struct bits8 {
short a : ; //从第1个字节开始,占1字节,使用3位
short : ; //占位,占21位,强制下一类型对齐到边界
char : ; //占位,从第3个字节开始,占3位
char b : ; //从第3字节第4位开始,使用5位
int i : ; //从第5个字节开始,占4字节,使用4位
};
它们的和为2字节(a)+1字节(b)+1字节(填充)+4字节(i)=8字节。
因为整体结构体还需要进行对齐,结构成员最大有效对齐参数值为4,所以整个结构为4的整数倍,满足条件,最后的总大小为8字节。
参考:
https://www.cnblogs.com/pure/archive/2013/04/22/3034818.html
https://jocent.me/2017/07/24/bit-field-detail.html
C++字节对齐与位域的更多相关文章
- C语言基础--结构体对齐,位域,联合体
结构体对齐 1--结构体对齐的原因与意义 许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值K(通常是2,4,8)的倍数,而这个k则被称为该数据类型的对齐模数 ...
- sizeof(结构体)和内存对齐以及位域
Win32平台下的微软C编译器的对齐策略: 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除: 备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该 ...
- c/c++ 字节对齐
c 字节对齐 概念: 结构体里会包括各种类型的成员,比如int char long等等,它们要占用的空间不同,系统为一个结构体开辟内存空间时,会有2种选择. 第一种:节省空间的方案,以上面的列子来说的 ...
- C语言字节对齐问题详解
引言 考虑下面的结构体定义: typedef struct{ char c1; short s; char c2; int i; }T_FOO; 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始 ...
- C/C++结构体字节对齐详解
结构体的sizeof先看一个结构体:struct S1{ char c; int i;}; sizeof(S1)在VC6中按默认设置得到的结果为8.我们先看看sizeof的定义——size ...
- C语言字节对齐问题详解(对齐、字节序、网络序等)
首先说明一下,本文是转载自: http://www.cnblogs.com/clover-toeic/p/3853132.html 博客园用的少,不知道怎么发布转载文章,只能暂时这样了. 引言 考虑下 ...
- C++进阶3.字节对齐 联合
C++进阶3.字节对齐 联合 20131011 多益和金山笔试 知识漏洞 20131011 前言: 今天下午是多益网络的笔试,整体感觉还好,但是找到很多的知识漏洞.一直笔试到6:00,然后紧张的从会生 ...
- <摘录>字节对齐(强制对齐以及自然对齐)
struct {}node; 32为的x86,window下VC下sizeof(node)的值为1,而linux的gcc下值为0: 一.WINDOWS下(VC--其实GCC和其原理基本一样,象这种问题 ...
- C语言字节对齐问题详解【转】
引言 转自:http://www.cnblogs.com/clover-toeic/p/3853132.html 考虑下面的结构体定义: 1 typedef struct{ 2 char c1; 3 ...
随机推荐
- ISCSI
感谢: https://www.cnblogs.com/wuchanming/p/4019660.html
- yarn web ui 参数详解
我们经常使用yarn调度,但是我们是否对调度队列显示参数真正了解呢? 下面我们来一一看看这些参数都是做什么用的,代表什么意思 hadoop是通过队列管理集群资源,翻开集群Web UI,找到Sc ...
- Jmeter性能结果分析
1.压测结果指标 Samples:表示一共发出的请求数 Average:平均响应时间,默认情况下是单个Request的平均响应时间(ms) Error%:测试出现的错误请求数量百分比.若出现错误就要看 ...
- 配置Nim的默认编译参数 release build并运行
配置Nim的默认编译参数 release build并运行 默认情况下nim编译是debug build,如果需要release build, 需要加上-d:release , release编译的命 ...
- Spring 内部注入bean
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- QTCPSOCKET 客户端已连接 而服务器无响应
最近在使用qt coding一个项目时,使用到了qtcpsocket模块来编写客户端与服务器.在windows平台下还能正常工作,但是在ubuntu平台下,客户端提示已连接时,服务器却没有响应.经过排 ...
- 神州数码HSRP(热备份路由协议)配置
实验要求:掌握HSRP配置方法 拓扑如下 R1 enable 进入特权模式 config 进入全局模式 hostname R1 修改名称 interface g0/6 进入端口 ip address ...
- 【Coucurrency-CountDownLatch】-20161203-0002
简介 java异步任务相关的工具.主要用在某些线程需要等到其他线程完成某些操作后才能执行的场景. 等待线程需要显示的调用wait方法,表示线程当前挂起,需要等到countdownLatch到0才执行. ...
- javamail发邮件
使用JavaMail发送一封简单邮件的步骤:(1)创建代表邮件服务器的网络连接信息的Session对象.(2)创建代表邮件内容的Message对象(3)创建Transport对象.连接服务器.发送Me ...
- easyui-tree-url-param
远古写法 url后面加参数?param1=1¶m2=2 动态添加 onBeforeLoad: function (node, param) { param.param1= 1, par ...