c++對象內存模型【內存對齊】


關於c++對象的內存模型 - 【內存對齊】方面,網上有大把的資料對此進行介紹,本篇文章僅對這些內容做一個梳理。

對齊規則,不同編譯器存在差異,本文在“vc6/32bit”windows平台進行編譯測試。(缺省為8字節對齊:對應編譯選項/Zp8

0.示例代碼:

 1 #pragma pack(1)         // 以1字節方式對齊
 2 class A1
 3 {
 4     char    a;
 5     short    b;
 6 };
 7 #pragma pack()           // 使用缺省對齊方式
 8  
 9 class A2
10 {
11     char    a;
12     short    b;
13 };
14 
15 /*  測試 */
16 int a1 = sizeof(A1);    // 3
17 int a2 = sizeof(A2);    // 4

A1內存模型(大小:3字節)

 

A2內存模型(大小:4字節)

1. 偽命令用法說明:

#pragma pack(n) // 使用自定義n字節對齊  n可以為1,2,4,8,16

#pragma pack()   // 使用缺省字節對齊(缺省為8字節對齊

#pragma Pack(push)   // 存放當前字節對齊到棧頂

#pragma Pack(push, n)  // 將n字節對齊方式壓入棧頂,並啟用自定義n字節對齊方式

/***  等價於  ***/

=>  #pragma Pack(push) 

=>  #pragma Pack(n) 

#pragma Pack(pop)  // 彈出棧頂,然后啟用新棧頂字節對齊方式【彈出后,棧為空,則恢復為缺省字節對齊】

2. 詳細解釋:

3. 內存對齊規則

(1)對於class(struct/union)的各個成員,第一個成員位於偏移為0的位置,以后每個數據成員的偏移量必須是min{#pragma pack()指定的數該數據成員的自身長度} 的倍數。

(2)在數據成員完成各自對齊之后,class(struct/union)本身也要按照min{#pragma pack()指定的數class(struct/union)中最大基本數據成員長度}進行對齊。

4. 為什么要內存對齊

(1)硬件限制:不是所有的硬件平台都能訪問任意地址上的數據;某些硬件平台只能在某些地址處取特定類型的數據,否則拋出硬件異常。

(2)提高性能:內存8字節對齊(注:cpu訪問byte、WORD、DWORD、__int64類型的數據時,只用一次內存訪問)后,CPU的內存訪問速度大大提升。

5. 那些情況要考慮內存對齊

(1)在不同平台之間(比如在Windows 與Linux之間),不同模塊之間(dll與exe之間)傳遞二進制流(比如結構體),必須要定義相同的對齊方式。

(2)序列化與反序列化的操作時,也必須要定義相同的對齊方式。

6. 補充

對於gcc編譯器:
__attribute((aligned (n)))  讓所作用的結構成員對齊在n字節自然邊界上。如果結構中有成員的長度大於n,則按照最大成員的長度來對齊。
__attribute__ ((packed))  取消結構在編譯過程中的優化對齊,按照實際占用字節數進行對齊。

// sizeof(struct test)=8
struct test
{
char x1;
short x2;
float x3;
char x4;
}__attribute__ ((packed));

visual studio編譯器的為:

__declspec(align(n)) 讓所作用的結構成員對齊在n字節自然邊界上。如果結構中有成員的長度大於n,則按照最大成員的長度來對齊。

__declspec(align(32)) struct Str1
{
   int a, b, c, d, e;
};

 

7. 外部參考   http://www.cppblog.com/snailcong/archive/2009/03/16/76705.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM