C++成员对齐方式探讨
本文參考了《高質量程序設計指南——C++/C語言》一書
有不妥之處懇請指正
一、自然對齊
某些基于RISC(精簡指令集)的CPU比方SPARC、PowerPC等。採用高字節和高字在低地址存放、低字節和低字在高地址存放的大端模式存儲。而且把最高字節的地址作為變量的首地址。
在這樣的自然的存儲格式中,要求變量在內存中的存放位置必須自然對齊,否則CPU會報告異常。所謂自然對齊,就是基本數據類型(主要是short、int、double)的變量不能簡單地存儲于內存中的隨意地址處。它們的起始地址必須可以被它們的大小整除。
比如。在32位平臺下,int和指針類型變量的地址應該能被4整除。而short變量的地址應該都是偶數,bool和char則沒有要求。所以。基于這樣的CPU架構的平臺,編譯器將依照自然對齊的要求來為每一個變量生成邏輯地址,C++/C編譯器亦如此。
而Intel系列CPU採用小端模式來存放基本類型變量,即低字節和低字在低地址存放、高字節和高字在高地址存放。而且把最低字節的地址作為變量的首地址。在Intel系列CPU這樣的硬件平臺上。并不嚴格要求基本數據類型變量在內存中必須自然對齊,相同也不會要求復合類型變量必須自然對齊。可是VC++在處理程序時,為了提高CPU的處理速度,對復合類型變量做了成員對齊處理。
二、成員對齊
VC++在處理復合數據類型成員變量時默認遵循下面三種原則:
(1)??? 復合類型對象的首地址要能被占用字節數最多的成員變量的字節數整除。
(2)??? 復合類型對象占用的內存空間大小要能被占用字節數最多的成員變量的字節數整除。
(3)??? 各成員變量存放的起始地址相對于復合結構的起始地址的偏移量必須為該變量的類型所占用的字節數的倍數。
舉比例如以下:
struct exm
{
?????? bool a;
?????? double b;
?????? bool c;
};
它是怎么存儲的?
首先,在內存中找一個能被8整除的起始地址。然后分配24個字節。
為什么是24個而不是10個?或者是16個?
這是由于原則(3)的緣故,變量b占8個字節,那么它相對于結構的起始地址的偏移量必須為8的倍數,因此盡管a僅僅占一個字節,但后面會補上7個字節。
那么為什么變量c也占8個字節啊?這是由于原則(2)的緣故。由于在結構體exm中。占用字節數最多的是變量b。8個字節,所以exm占用的空間大小應能被8整除,如今a和b已經占用16個字節了,而c至少要占用一個字節,因此會在c后補上7個字節,變成24個字節。
把exm成員調換一下。變為:
struct exm
{
?????? double b。
?????? bool a。
?????? bool c;
};
它的大小就變成16個字節了。
當然,我們也能夠在程序中指定對齊方式。這時上述原則將不再成立。假設在程序中指定對齊方式。則對于復合結構中的變量,假設占用空間不足指定對齊字節。且假設依照默認對齊方式占用的空間將比指定的對齊方式大,則將按指定對齊方式補足,比如:
#pragmapack(4) //依照4字節邊界對齊
struct exm
{
?????? bool a;
?????? double b;
?????? bool c;
};
在VS2010中,它占用16個字節空間。
分析:變量a假設依照默認對齊方式要占8位,但它本身是bool型變量,占一位,指定對齊方式為4字節對齊,則a將被補齊為4字節。同理變量c也一樣。
把exm成員換一下位置:
#pragmapack(4) //依照4字節邊界對齊
struct exm
{
?????? double b;
?????? bool a;
?????? bool c。
};
則exm占12位。
總結
以上是生活随笔為你收集整理的C++成员对齐方式探讨的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (转)基于MVC4+EasyUI的Web
- 下一篇: 5G研发大幕开启 终端硝烟已燃