對於cpu從記憶體讀取資料,並不是我們想象的那樣,直接前去讀取對應的大小,為了提公升效率和速度,cpu會按照記憶體讀取粒度的大小來讀取內從中的資料,比如說如果記憶體讀取粒度是4個位元組,那麼cpu會一次讀取4個位元組的記憶體,就算讀取char型別的資料,雖然它只佔1個位元組,但是cpu依然會讀取4個位元組,然後從四個位元組中取出char型別的資料,因此就產生了記憶體對齊這樣的問題,也就是在結構體這樣的型別中,他所佔的大小並不一定是組成它的成員的大小之和,他還需要考慮記憶體對齊的問題。記憶體對齊主要是為了提高讀取速度。
其中如果 不記憶體對齊 部分 cpu還不支援不記憶體對齊,也就是說可能會產生直接崩潰的現象。
因此記憶體對齊 也是為了平台移植的原因。
還有記憶體對齊可以提高訪問記憶體的速度
分為2步:
1. 結構體中的型別 第乙個型別偏移量是0 其他型別要根據規則來計算偏移量 偏移量為 min(#pragma pack(),該型別所佔位元組大小) 的倍數
2. 結構體最終的總大小是 min(#pragma pack(),結構體中最大型別的位元組大小) 的倍數
struct structa
struct structb
對於這兩個結構體 structa和structb 在記憶體中佔的大小 卻不是一樣的
sizeof(structa) : 12位元組
sizeof(structb) : 8位元組
這是為什麼呢? 結構體中內容一樣,當時在記憶體中所佔的大小卻是不一樣的
下面我們就按照上述的記憶體對齊規則來計算一下他倆在記憶體中所佔的大小:
structa:
struct structa
首先 它的第乙個成員 char c; 大小為 1個位元組 由於是第乙個元素 所以它的偏移量為0 處於 0位置
第二個成員 int a; 大小為 4個位元組 #pragma pack() 的大小是 8位元組 min(#pragma pack(),變數大小) = 4位元組 因此偏移量為4的倍數 為4
處於4 5 6 7位址位置 1 2 3 位置空閒
第三個成員 short s; 大小為 2個位元組 #pragma pack() 的大小是 8位元組 min(#pragma pack(),變數大小) = 2位元組 因此偏移量為2的倍數 為
8 處於 8 9位置
這樣就完成了第一步的對齊
之後進行第二步對齊,由於結構體中最大的成員是int 佔4個位元組 #pragma pack()等於8 因此 結構體總的大小應該為 4的倍數 所以應該為12位元組
這樣就計算出了記憶體中占有的實際記憶體大小
structb:
struct structb
pragma pack() = 8
首先它的第乙個成員為short型別 偏移量為0 占有 0 1位置
第二個成員為char型別 大小為1 因此偏移量為 1的倍數 為 2 佔 2 這個位置
第三個成員為int 型別 大小為4位元組 因此偏移量為 4的倍數 也就是 4
佔 4 5 6 7 位置 3 位置空閒
因此 第一步對齊後 占有 0 -7的位址位置 大小為8位元組
而結構體中最大的為int 4個位元組 而8是 4的倍數 因此 此結構體在記憶體中占有的大小就是 8個位元組
這樣就解釋清楚了記憶體對齊的規則,希望我以後不會忘記。。。。
記憶體對齊規則
1 平台原因 移植原因 不是所有的硬體平台都能訪問任意位址上的任意資料的 某些硬 件平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。2 效能原因 資料結構 尤其是棧 應該盡可能地在自然邊界上對齊。原因在於,為了訪問 未對齊的記憶體,處理器需要作兩次記憶體訪問 而對齊的記憶體訪問僅需要一次...
記憶體對齊規則
隔了很久,搞忘了對齊的規則,現在重新複習了下,記下來謹防以後又忘記。1 可以根據 pragma pack 設定對齊係數,且叫為n 2 結構體中,對比每個成員變數自身的大小和n的大小。取小的個為標準,把這個小的叫a吧,稱為按a對齊 3 每個變變數的起始位址需要為a的整數倍,不是整數倍的則補齊。4 最後...
記憶體對齊 記憶體對齊規則解釋 記憶體對齊原理
一 記憶體對齊的原因 我們都知道計算機是以位元組 byte 為單位劃分的,理論上來說cpu是可以訪問任一編號的位元組資料的,我們又知道cpu的定址其實是通過位址匯流排來訪問記憶體的,cpu又分為32位和64位,在32位的cpu一次可以處理4個位元組 byte 的資料,那麼cpu實際定址的步長就是4個...