前言 Steam是由美國電子游戲商Valve於2003年9月12日推出的數字發行平臺,被認為是電腦游戲界最大的數位發行平臺之一,Steam平臺是全球最大的綜合性數字發行平臺之一。玩家可以在該平臺購買、下載、討論、上傳和分享游戲和軟體。 而每周的steam會開啟了一輪特惠,可以讓游戲打折,而玩家就會 ...
概述
問題:
struct Foo1
{
char a;
char b;
int c;
}
- 32位系統中,Foo1的對象在記憶體中占用多少記憶體?若是改變變數a,b,c在記憶體中的位置順序,記憶體大小會變化麽?
- 什麼是記憶體對齊?
- 為什麼要記憶體對齊?
- 如何記憶體對齊?
創建結構體Foo
struct Foo
{
int a;
int b;
}
查看Foo的記憶體佈局
1>class Foo size(8):
1> +---
1> 0 | a
1> 4 | b
1> +---
在32位的系統中,int占4個位元組,Foo記憶體佈局占用8個位元組記憶體。
創建結構體Foo1,Foo2,Foo3
struct Foo1
{
char a;
char b;
int c;
};
struct Foo2
{
char a;
int c;
char b;
};
struct Foo3
{
int c;
char a;
char b;
};
查看Foo1,Foo2,Foo3的記憶體佈局
1>class Foo1 size(8):
1> +---
1> 0 | a
1> 1 | b
1> | alignment member (size=2)
1> 4 | c
1> +---
1>class Foo2 size(12):
1> +---
1> 0 | a
1> | alignment member (size=3)
1> 4 | c
1> 8 | b
1> | alignment member (size=3)
1> +---
1>class Foo3 size(8):
1> +---
1> 0 | c
1> 4 | a
1> 5 | b
1> | alignment member (size=2)
1> +---
- Foo1占用8個位元組,對齊2個位元組。
- Foo2占用12個位元組,a與b後各對齊3個位元組。
- Foo3占用8個位元組,對齊2個位元組
記憶體對齊會影響記憶體的分配,以上結構體的記憶體大小不是6個位元組。
記憶體對齊
現代電腦中記憶體空間都是按照 byte 劃分的,從理論上講似乎對任何類型的變數的訪問可以從任何地址開始,但是實際的電腦系統對基本類型數據在記憶體中存放的位置有限制,它們會要求這些數據的首地址的值是某個數k(通常它為4或8)的倍數。
記憶體對齊的意義
跨平臺
不是所有的硬體平臺都能訪問任意地址上的任意數據的;某些硬體平臺只能在某些地址處取某些特定類型的數據,否則拋出硬體異常。
提升性能
0 0 0 1 1 1 1 0 --不對齊
0 0 0 0 1 1 1 1 --對齊
記憶體對齊在不同環境下對性能的提升不盡相同,一種情況是:假使32位系統下,處理器讀取記憶體的粒度為4位元組。未對齊記憶體需要讀取兩次記憶體,併進行記憶體剔除,且有可能引發OS異常處理。
記憶體對齊規則
記憶體對齊是編譯器完成的,不同平臺不同編譯器記憶體對齊規則可能不同。
特定平臺的編譯器都有預設對齊繫數。gcc中預設#pragma pack(4),可以通過預編譯命令#pragma pack(n),n = 1,2,4,8,16來改變這一繫數。
有效對其值:是給定值#pragma pack(n)和結構體中最長數據類型長度中較小的那個。有效對齊值也叫對齊單位。
- 結構體第一個成員的偏移量為0,後面每個成員相對於結構體首地址的偏移量是該成員大小與有效對齊值中較小那個值的整數倍,不滿足條件則編譯器會在成員之間填充位元組以滿足條件。
- 結構體的總大小必須是有效對齊值的整數倍,不滿足條件則編譯器會在成員之間填充位元組以滿足條件。