环境:

  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++字节对齐与位域的更多相关文章

  1. C语言基础--结构体对齐,位域,联合体

    结构体对齐 1--结构体对齐的原因与意义 许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值K(通常是2,4,8)的倍数,而这个k则被称为该数据类型的对齐模数 ...

  2. sizeof(结构体)和内存对齐以及位域

    Win32平台下的微软C编译器的对齐策略: 1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除: 备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该 ...

  3. c/c++ 字节对齐

    c 字节对齐 概念: 结构体里会包括各种类型的成员,比如int char long等等,它们要占用的空间不同,系统为一个结构体开辟内存空间时,会有2种选择. 第一种:节省空间的方案,以上面的列子来说的 ...

  4. C语言字节对齐问题详解

    引言 考虑下面的结构体定义: typedef struct{ char c1; short s; char c2; int i; }T_FOO; 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始 ...

  5. C/C++结构体字节对齐详解

    结构体的sizeof先看一个结构体:struct S1{    char c;    int i;}; sizeof(S1)在VC6中按默认设置得到的结果为8.我们先看看sizeof的定义——size ...

  6. C语言字节对齐问题详解(对齐、字节序、网络序等)

    首先说明一下,本文是转载自: http://www.cnblogs.com/clover-toeic/p/3853132.html 博客园用的少,不知道怎么发布转载文章,只能暂时这样了. 引言 考虑下 ...

  7. C++进阶3.字节对齐 联合

    C++进阶3.字节对齐 联合 20131011 多益和金山笔试 知识漏洞 20131011 前言: 今天下午是多益网络的笔试,整体感觉还好,但是找到很多的知识漏洞.一直笔试到6:00,然后紧张的从会生 ...

  8. <摘录>字节对齐(强制对齐以及自然对齐)

    struct {}node; 32为的x86,window下VC下sizeof(node)的值为1,而linux的gcc下值为0: 一.WINDOWS下(VC--其实GCC和其原理基本一样,象这种问题 ...

  9. C语言字节对齐问题详解【转】

    引言 转自:http://www.cnblogs.com/clover-toeic/p/3853132.html 考虑下面的结构体定义: 1 typedef struct{ 2 char c1; 3 ...

随机推荐

  1. JAVA 第1课

    JAVA第一课 电脑识别的进制:二进制,八进制,十六进制 二进制来表示高低电压,类似于抗战时期的发报机.2进制的存储 8进制和16进制:计算器,在计算的时候有一定的临时存储,8位或者16位禁止的存储 ...

  2. 几个常用内核函数(《Windows内核情景分析》)

    参考:<Windows内核情景分析> 0x01  ObReferenceObjectByHandle 这个函数从句柄得到对应的内核对象,并递增其引用计数. NTSTATUS ObRefer ...

  3. ES6常用方法总结

    1.声明变量用let,声明常量用const(定义唯一的值),都没有预解释,也不存在变量提升: 2.箭头函数:有如下两种写法 1).表达式(函数体只有一行代码) a).let fn = p => ...

  4. mongoDB-Cannot change the size of a document in a capped collection:

    简单记录一下: 造成该问题的原因是集合被设置成了 固定集合 .固定集合的数据不能被修改.只能查找-删除-再插入

  5. python的标准数据类型

    python有5种标准的数据类型 1. number(数字) int(有符号的整形) long(长整[也可以代表八进制和16进制]) float(浮点型) complex(复数类型) 2.string ...

  6. oracle 根据一个表更新另一个表内容

    declarecursor c_col is select * from xtgl_jgmcbm where substr(v_jgbm,0,2)in('41');--v_sjbm in( selec ...

  7. [mock open]PyUnit执行单元测试时使用字符串模拟文件对象

    def mock_open(data): from StringIO import StringIO stmp = StringIO(data) return stmp _open = __built ...

  8. oracle导入导出功能

    1.普通版:oracle导入导出功能:导出exp 用户名/密码@SID file=f:\xx.dmp owner=用户名 导入imp 用户名/密码@SID full=y file=f:\xx.dmp ...

  9. iBATIS 调试

    在写完sql语句以后,如果参数有问题.还真不知道该如何看参数.原来Ibatis 是通过日志输出,看到参数的.IBatis 内置的日志输出是log4net,所以可以参考ibatis的api.照着复制其配 ...

  10. Beta冲刺第二周王者荣耀交流协会第六次会议

    1.立会照片 成员:王超,高远博,冉华,王磊,王玉玲,任思佳,袁玥全部到齐. master:任思佳 2.时间跨度: 2017年11月22日 12:00 — 12:20,总计20分钟. 3.地点: 一食 ...