数据对齐

摘要:
结构S1{chark;doublei;charc;};Sizeof的值是24,而不是10,因为数据是对齐的。如果每个字段的值是连续存储的,那么双类型i可以分配在两个8字节的存储器块中,然后可能需要执行两次存储器访问。当前的内存分配是这样的,即k、i和c都占用8个字节,因此在一次内存访问后可以获得双倍类型i值。以同样的方式,S4中的所有元素都是连续的,并且S4中的元素也遵循数据对齐原则。事实上,我们可以这样看待S4:structS4{char;intc;doublei;inti[5];};这更容易理解。

许多计算机系统对数据类型的合法地址做了一些限制,要求某种数据类型对象的地址必须是某个值K(2,4,8)的倍数,这种堆积限制简化形成了处理器和存储器系统之间接口的硬件设计,总之就是为了方便高效的读取数据,于是就有了数据对齐。

struct S1

{

   char k;

   double i;

   char c; 

};

Sizeof(S1)的值为24,而不是10,其原因就是数据对齐,如果是连续的存每个字段的值,那么double类型的i就可能分配在两个8字节的存储器块中,那么可能就要执行两次存储器访问,而现在的内存分配至这样的,k,i,c都占用8个字节,这样访问1次存储器就能得到double类型的i的值。k后面会有7个字节被浪费掉,也就是说i的偏移量是8,同样的c后面有7个字节被浪费掉,尽管它后面没有任何字段。这样显然太浪费内存了。如果我们将i和c的位置交换一下得到如下struct S2:

struct S2

{

   char k;

   char c;  

   double i;

};

现在Sizeof(S2)的值为16,而不是10也不是24。为了方便取出struct中最长的字段,即方便一次性读出,这个最长的字段前面和后面的字段所占的长度都必须是它的倍数,在这里就是double的长度8的倍数。而k所占的长度加c所占的长度为2,小于8,所以k和c的内存是连续的,c后面接着的是6个空白字节然后就是i所占的8个字节。我想你会有这样的疑问:为什么不直接把S1编译成S2?我只能说我也不知道,但有一个类似的情况就是:在类的初始化列表中,先定义的字段先初始化。那么在这里先定义的先分配内存, 还有就是struct根本没有产生多与的东西,来区分每个字段,要是编译器把他们的内存结果重组了,它又怎么知道自己读的是哪个字段呢。以上几句只是阿汉的个人理解,没有任何证明。

有了上面的解释说明,在看一些简单的struct所需的内存就容易了。

struct S3

{

   char k;

   int c;

   double i;

};

Sizeof(S3):16,k与c连续,c后面3个字节空白,紧接着i占8个字节,共16个字节。

struct S4

{

   S3 a;

   int i[5];

};

那么sizeof(S4)的值为多少呢?40,a占16个字节,i占24个字节。a占16个字节我们是知道的,为什么int i[5]占24个字节,而不是20个字节呢,还是因为数据对齐,因为S3中的double i占8个字节,那么i占用的字节长度就一定是8的倍数,所以int i[5]占24个字节,而不是20个字节,如果S4中i的定义是int i[4],则i占16个字节,大家都没话说,没有疑问。

同样的S4中的所有元素都是连续(会出现因为数据的长度不同而出现间隙空白),S4中的元素也会遵守数据对齐原则,其实我们可以把S4看成如下的样子:

struct S4

{

   char k;

   int c;

   double i;

int i[5];

};

这样就好理解多了。

如果S3和S4的样子如下

struct S3

{

   char k;

   int c;

   int i;

};

 

struct S4

{

   S3 a[2];

   double i[5];

};

sizeof(S4)等于多少呢?

作者:陈太汉

博客:http://www.cnblogs.com/hlxs/

免责声明:文章转载自《数据对齐》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Delphi部分函数、命令、属性中文说明Flex 布局教程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Oracle 求昨天 上个月 去年 日期

到公司发现有一个报表没有收到,查看后发现原来是Oracle数据源异常。 SELECT to_char(SYSDATE - interval '1' month, 'yyyyMMdd') AS fromdata, to_char(SYSDATE - interval '1' day, 'yyyyMMdd') AS en...

java 接收 char字符型

import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.Scanner;public class GetChar {public static void main(String[] args)throws Exception {//通过扫描类输入Scan...

Transfer-Encoding: chunked

Http1.1中 使用 chunked 编码传送时 没有CONTENT_LENGTH,下载之前无法确定要下载的大小. Wininet中已经内嵌该传输协议,要查看chunked块的大小只能socket底层编写获取报文. Wininet能不能直接访问原报文需走旁路. // socket_http.cpp : Defines the entry point...

String和datetime在SQL中和在C#中相互转换方法总结

String和datetime之间相互转换方法总结: SQL中的转换方法: 一,将string转换为datetime,主要是使用Convert方法, 方法,Convert(datetime [ ( length ) ] , expression, [style])           如: convert(datetime,Datetime.Now,120...

c++对象模型和RTTI(runtime type information)

在前面已经探讨过了虚继承对类的大小的影响,这次来加上虚函数和虚继承对类的大小的影响。 先来回顾一下之前例子的代码: #include <iostream> using namespacestd; classBB { public: intbb_; }; class B1 : virtual publicBB { public:...

C++雾中风景番外篇4:GCC升级二三事

最近将手头上负责的项目代码从GCC 4.8.2升级到了GCC 8.2。(终于可以使用C++17了,想想后续的开发也是很美好啊~~)不过这个过程之中也遇到了一些稀奇古怪的问题,在这里做一个简单的记录,希望后续有同学遇到类似的问题能作为参考。 1. error: unable to find string literal operator 'operator"...