您的位置:首页 > 编程语言 > C语言/C++

关于struct类型的sizeof探究

2016-04-06 15:36 369 查看


关于struct类型的sizeof探究

1、struct类型字节对齐先来看一个例子
1

2

3

4

5

6

7
struct
 
db

{

       
char
 
c1;

       
int
 
i1;

       
char
 
c2;

       
float
 
f;

};


结构的第一个成员c1,其偏移地址为0,占据了第1个字节。第二个成员i1为int类型,其起始地址必须4字节对界,因此,编译器在c1和i1之间填充了3个空字节。结构的第三个成员c2恰好落在其自然对界地址上,在它们前面不需要额外的填充字节,但是c2和f之间必须再填充3个空字节,因为第四个成员f必须对其4字节地指处,因此整个db结构占用(1+3)+ 4 + (1+3) +4 = 16字节。现在大概明白了大致的对其方式。

    但是需要强调的是,每个成员有其自己的对其方式,结构体本身也有对其方式。下面看这个例子:看看它占用多少字节。
1

2

3

4

5

6
struct
 
db

{

      
char
 
c1;

      
int
 
i1;

      
char
 
c2;

};


如果对这个理解不是很深刻的话,这个很可能就会出错了,也许你会计算成(1+3)+ 4 + 1 = 9字节。这一就错了。。。因为结构体本身的对齐方式是以成员中对齐字节数最大的成员为标准的,在这里就是int的4字节,也就是说这个db结构体必须对齐到4的整数倍地址上。那么这意味着什么?意味着最后一个char型必须在后面填充3个空字节,整个db结构体占用(1+3) + 4 + (1+3) = 12字节。

最后再试试看下面这个结构体占用字节会是多少?

1

2

3

4

5

6
struct
 
db

{

       
char
 
c1;

       
char
 
c2;

       
char
 
c3;

};


答案是:3.

2、关于double类型出现在struct里面

先看下例

1

2

3

4

5

6

7
struct
 
db

{

       
char
 
c1;

       
int
 
i1;

       
float
 
f;

       
double
 
d1;

};


这个会占用多少字节呢?首先double占用8字节是没错的,理论上讲,答案应该是(1+3)+ 4 + 4 + (4)+ 8 = 24字节。没错,这在x64系统下确实是sizeof(struct db) = 24字节。但是在x86系统下我实验了下它死活就是sizeof(struct db) = 20. 

然后后来我实验了好几个例子,都是这种情况,所以目前我就这么下一个结论吧:可能是在x86下最大的对齐字节数也就是4了,因为当 用语句 #pragma pack(2) 限定对齐方式小于4的时候都可以达到目的,一旦超过4就无效了。(谁有更好的解释希望拿出来分享啊~)

3、为什么要对齐?

  (摘自网上博客http://www.cppblog.com/snailcong/archive/2009/03/16/76705.html)

     内存对齐的主要作用是:

1)平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2)性能原因:经过内存对齐后,CPU的内存访问速度大大提升。具体原因稍后解释。

看下图:

图一:



这是普通程序员心目中的内存印象,由一个个的字节组成,而CPU并不是这么看待的。

图二:



CPU把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的。块大小成为memory
accessgranularity(粒度) 本人把它翻译为“内存读取粒度”。

假设CPU要读取一个int型4字节大小的数据到寄存器中,分两种情况讨论:

1、数据从0字节开始

2、数据从1字节开始

再次假设内存读取粒度为4。

图三:



当该数据是从0字节开始时,很CPU只需读取内存一次即可把这4字节的数据完全读取到寄存器中。

当该数据是从1字节开始时,问题变的有些复杂,此时该int型数据不是位于内存读取边界上,这就是一类内存未对齐的数据。

图四:



此时CPU先访问一次内存,读取0—3字节的数据进寄存器,并再次读取4—5字节的数据进寄存器,接着把0字节和6,7,8字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器。对一个内存未对齐的数据进行了这么多额外的操作,大大降低了CPU性能。

这还属于乐观情况了,上文提到内存对齐的作用之一为平台的移植原因,因为以上操作只有有部分CPU肯干,其他一部分CPU遇到未对齐边界就直接罢工了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ struct sizeof