先来看看什么是对齐。现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序地一个接一个地排放,这就是对齐。

一、相关概念

(1)数据类型自身对齐值:基本数据类型的自身所占空间大小。

(2)指定对齐值:使用#pragam pack(value)时,指定的对齐值value。

(3)结构体或类的自身对齐值:其中成员对齐值最大的那个值。

(4)结构体和类的有效对齐值:自身对其值和指定对其值中较小的那个值。

二、示例代码

1、示例一

32位机器上定义如下结构体:

  1. struct xx
  2. {
  3. long long _x1;
  4. char _x2;
  5. int _x3;
  6. char _x4[];
  7. static int _x5;
  8. };
  9. int xx::_x5;

正确答案是24。

你做对了么?下面给出解释:

每个元素的起始偏移地址要能被其类型大小整除,结构体整体大小要能被结构体中最大数据类型整除。

结构体的有效对齐值的确定:

  1. 当未明确指定时,以结构体中最长的成员的长度为其有效值
  2. 当用#pragma pack(n)指定时,以n和结构体中最长的成员的长度中较小者为其值。
  3. 当用__attribute__ ((__packed__))指定长度时,强制按照此值为结构体的有效对齐值

2、示例二

32位环境下,给定结构体

  1. struct A
  2. {
  3. char t:;
  4. char k:;
  5. unsigned short i:;
  6. unsigned long m;
  7. };
问 sizeof ( A ) =_____;

答案是8,这次你做对了么?

解析:变量后面加 :  然后加数字表示位域,也就是说着代表按位来存放的,不是按字节,这是计算机为了节约空间的一种方式。char 类型是一个字节(8个位),又因为 t 和 k 加起来刚好8位,也就是一个字节,所以存储在一个位。然后 short 占一共16个位,需要从地址为2的倍数的位置存储,所以前边空出一个字节。又因为放了8个,剩下8个不够后面long存放,所以算两个字节。因为long在32是4个字节,所以一共 1 + 1 + 2 + 4 = 8。然后再进行结构体对齐,所以最终结果就是 8。

三、知识点

1、位域的sizeof

  1. 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
  2. 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
  3. 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
  4. 如果位域字段之间穿插着非位域字段,则不进行压缩;
  5. 整个结构体的总大小为最宽基本类型成员大小的整数倍。

2、内存对齐的3大规则

  1. 对于结构体的各个成员,第一个成员的偏移量是0,排列在后面的成员其当前偏移量必须是当前成员类型的整数倍
  2. 结构体内所有数据成员各自内存对齐后,结构体本身还要进行一次内存对齐,保证整个结构体占用内存大小是结构体内最大数据成员的最小整数倍
  3. 如程序中有#pragma pack(n)预编译指令,则所有成员对齐以n字节为准(即偏移量是n的整数倍),不再考虑当前类型以及最大结构体内类型

作者:耑新新,发布于  博客园

转载请注明出处,欢迎邮件交流:zhuanxinxin@aliyun.com

C/C++有效对齐值的确定的更多相关文章

  1. 小甲鱼PE详解之区块描述、对齐值以及RVA详解(PE详解06)

    各种区块的描述: 很多朋友喜欢听小甲鱼的PE详解,因为他们觉得课堂上老师讲解的都是略略带过,绕得大家云里雾里~刚好小甲鱼文采也没课堂上的教授讲的那么好,只能以比较通俗的话语来给大家描述~ 通常,区块中 ...

  2. (转)CPU Cache与内存对齐

    转自:http://blog.csdn.net/zhang_shuai_2011/article/details/38119657 原文如下: 一. CacheCache一般来说,需要关心以下几个方面 ...

  3. C语言:内存字节对齐详解[转载]

    一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...

  4. struct内存对齐1:gcc与VC的差别

    struct内存对齐:gcc与VC的差别 内存对齐是编译器为了便于CPU快速访问而采用的一项技术,对于不同的编译器有不同的处理方法. Win32平台下的微软VC编译器在默认情况下采用如下的对齐规则:  ...

  5. Nginx学习笔记(五) 源码分析&内存模块&内存对齐

    Nginx源码分析&内存模块 今天总结了下C语言的内存分配问题,那么就看看Nginx的内存分配相关模型的具体实现.还有内存对齐的内容~~不懂的可以看看~~ src/os/unix/Ngx_al ...

  6. ARM字节对齐问题详解

    一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这 ...

  7. C语言中内存对齐方式

    一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...

  8. C语言之字节对齐

    在C语言编程中,有时为了达到减少运行的时间的目的,需要浪费一些空间:而有时为了节省空间,使它的运行时间增长.而字节对齐则是为了访问效率,用空间换取时间. 要掌握字节对齐,首先得明确一下四个概念: 1. ...

  9. C ~ C语言字节对齐

    1. 什么是对齐? 现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型 ...

随机推荐

  1. ql Server 2012完全卸载方法

    第一步,在控制面板里面找到程序——卸载程序这一项,打开之后就会是这样的了 第二步,经过第一步打开卸载程序后,在里面找到Microsoft SQLserver 2012 (64-bit)这一项,可以通过 ...

  2. cglib动态代理是通过继承父类的方式进行代理的 不是通过接口方式进行动态代理的 因此可以对普通的类进行代理

    cglib动态代理是通过继承父类的方式进行代理的 不是通过接口方式进行动态代理的

  3. poj1741 Tree(点分治)

    题目链接:http://poj.org/problem?id=1741 题意:求树上两点之间距离小于等于k的点对的数量 思路:点分治模板题,推荐一篇讲的非常好的博客:https://blog.csdn ...

  4. 洛谷 P2765 魔术球问题 解题报告

    P2765 魔术球问题 题目描述 问题描述: 假设有\(n\)根柱子,现要按下述规则在这\(n\)根柱子中依次放入编号为\(1,2,3,\dots\)的球. \((1)\) 每次只能在某根柱子的最上面 ...

  5. 【uoj428】普通的计数题

    Portal --> uoj428 Solution 不会胖子的一个log正解qwq只能怂怂滴写分治了qwq ​ 首先就是一个我想不到的转化qwq ​ 我们将第\(i\)次操作加入的数看成一个编 ...

  6. C++委托模式

    希望想理解C++委托的同学,能够从代码中悟出其中的原理.有什么不太清楚的地方,欢迎留言交流. #include <bits/stdc++.h> using namespace std; # ...

  7. Zabbix应用五:Zabbix监控多Tomcat

    利用Zabbix Trapper方式监控多Tomcat实例 Zabbix自带的模版(JMX Tomcat.JMX Generic)默认只能在一台机器上监控一个tomcat实例(因为监控项中的key不能 ...

  8. Spark记录-Scala异常与处理

    Scala try-catch语句 Scala提供try和catch块来处理异常.try块用于包含可疑代码.catch块用于处理try块中发生的异常.可以根据需要在程序中有任意数量的try...cat ...

  9. JeeSite 4.x 树形结构的表设计和用法

    有些同仁对于 JeeSite 4 中的树表设计不太了解,本应简单的方法就可实现,却写了很多复杂的语句和代码,所以有了这篇文章. 在 JeeSite 4 中的树表设计我还是相对满意的,这种设计比较容易理 ...

  10. Linux - 用户操作

    常用命令 users # 显示所有的登录用户 groups # 列出当前用户和他所属的组 who -q # 显示所有的登录用户 groupadd # 添加组 useradd user # 建立用户 p ...