详解结构体、类等内存字节对齐

详解结构体、类等内存字节对齐

ID:9116494

大小:69.70 KB

页数:7页

时间:2018-04-18

详解结构体、类等内存字节对齐_第1页
详解结构体、类等内存字节对齐_第2页
详解结构体、类等内存字节对齐_第3页
详解结构体、类等内存字节对齐_第4页
详解结构体、类等内存字节对齐_第5页
资源描述:

《详解结构体、类等内存字节对齐》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库

1、先说个题外话:早些年我学C程序设计时,写过一段解释硬盘MBR分区表的代码,对着磁盘编辑器怎么看,怎么对,可一执行,结果就错了。当时调试也不太会,又根本没听过结构体对齐这一说,所以,问题解决不了,好几天都十分纠结。后来万般无奈请教一个朋友,才获悉可能是结构体对齐的事,一查、一改,果真如此。 问题是解决了,可网上的资料多数只提到内存对齐是如何做的,却鲜有提及为什么这样做(即使提,也相当简单)。笔者是个超级健忘者,很难机械式的记住这些破规则,于是仔细想了想,总算明白了原因,这样,这些对齐的规则也就不会再轻易忘记了。    不光结构体存在内存对齐一说,类

2、(对象)也如此,甚至于所有变量在内存中的存储也有对齐一说(只是这些对程序员是透明的,不需要关心)。实际上,这种对齐是为了在空间与复杂度上达到平衡的一种技术手段,简单的讲,是为了在可接受的空间浪费的前提下,尽可能的提高对相同运算过程的最少(快)处理。先举个例子: 假设机器字长是32位的(即4字节,下面示例均按此字长),也就是说处理任何内存中的数据,其实都是按32位的单位进行的。现在有2个变量:   1.char A; 2.int B;    假设这2个变量是从内存地址0开始分配的,如果不考虑对齐,应该是这样存储的(见下图,以intel上的littl

3、eendian为例,为了形象,每16个字节分做一行,后同):  因为计算机的字长是4字节的,所以在处理变量A与B时的过程可能大致为:  A:将0x00-0x03共32位读入寄存器,再通过左移24位再右移24位运算得到a的值(或与0x000000FF做与运算)  B:将0x00-0x03这32位读入寄存器,通过位运算得到低24位的值;再将0x04-0x07这32位读入寄存器,通过位运算得到高8位的值;再与最先得到的24位做位运算,才可得到整个32位的值。  上面叙述可知,对a的处理是最简处理,可对b的处理,本身是个32位数,处理的时候却得折成2部分

4、,之后再合并,效率上就有些低了。  想解决这个问题,就需要付出几个字节浪费的代价,改为下图的分配方式:  按上面的分配方式,A的处理过程不变;B却简单得多了:只需将0x04-0x07这32位读入寄存器就OK了。  我们可以具体谈结构体或类成员的对齐了:  结构体在编译成机器代码后,其实就没有本身的集合概念了,而类,实际上是个加强版的结构体,类的对象在实例化时,内存中申请的就是一些变量的空间集合(类似于结构体,同时也不包含函数指针)。这些集合中的每个变量,在使用中,都需要涉及上述的加工原则,自然也就需要在效率与空间之间做出权衡。  为了便捷加工连续

5、多个相同类型原始变量,同时简化原始变量寻址,再汇总上述最少处理原则,通常可以将原始变量的长度做为针对此变量的分配单位,比如内存可用64个单元,如果某原始变量长度为8字节,即使机器字长为4字节,分配的时候也以8字节对齐(看似IO次数是相同的),这样,寻址、分配时,均可以按每8字节为单位进行,简化了操作,也可以更高效。  系统默认的对齐规则,追求的至少两点:1、变量的最高效加工2、达到目的1的最少空间   举个例子,一个结构体如下: 1.//bywww.datahf.netzhangyu2.typedef struct T3.{ 4.    char

6、 c;//本身长度1字节 5.    __int64 d; //本身长度8字节6.    int e; //本身长度4字节7.    shortf; //本身长度2字节8.    char g; //本身长度1字节9.    short h; //本身长度2字节10.};   假设定义了一个结构体变量C,在内存中分配到了0x00的位置,显然:  对于成员C.c 无论如何,也是一次寄存器读入,所以先占一个字节。  对于成员C.d 是个64位的变量,如果紧跟着C.c存储,则读入寄存器至少需要3次,为了实现最少的2次读入,至少需要以4字节对齐;同时对于

7、8字节的原始变量,为了在寻址单位上统一,则需要按8字节对齐,所以,应该分配到0x08-0xF的位置。  对于成员C.e 是个32位的变量,自然只需满足分配起始为整数个32位即可,所以分配至0x10-0x13。  对于成员C.f 是个16位的变量,直接分配在0x14-0x16上,这样,反正只需一次读入寄存器后加工,边界也与16位对齐。  对于成员C.g 是个8位的变量,本身也得一次读入寄存器后加工,同时对于1个字节的变量,存储在任何字节开始都是对齐,所以,分配到0x17的位置。  对于成员C.h 是个16位的变量,为了保证与16位边界对齐,所以,分

8、配到0x18-0x1A的位置。  分配图如下(还不正确,耐心读下去):  结构体C的占用空间到h结束就可以了吗?我们找个示例:如果定义一

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。