關於結構體中各個變數在記憶體中所佔空間

2021-10-03 19:22:40 字數 1824 閱讀 7892

首先,我們來看一下下面這段**。

#include

intmain()

part1;

struct bpart_one;

printf

("%d %d"

,sizeof

(part1)

,sizeof

(part_one));

return0;

}

我們不妨假設這兩個結構體所佔記憶體位元組數為其包含的各個變數所佔位元組數的代數和,那麼,執行結果應該是1 + 4 + 8 和 1 + 8 + 4,也就是13 13。但是,最終我們得到的執行結果卻是這樣子的:

這就不得不提到計算機中存在的一種叫做記憶體對齊的機制了。

每個特定平台上的編譯器都有自己的預設「對齊係數」(也叫對齊模數)。程式設計師可以通過預編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一係數,其中的n就是你要指定的「對齊係數」。

資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員的對齊按照#pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。

結構(或聯合)的整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大資料成員長度中,比較小的那個進行。

結合1、2可推斷:當#pragma pack的n值等於或超過所有資料成員長度的時候,這個n值的大小將不產生任何效果。

注:#pragma pack(n)是用於設定變數以n位元組對齊方式對齊(即變數起始位置在記憶體空間中的偏移量是對齊係數的倍數)。

另外,不得不提到的是,我們的計算機的對齊策略一般是這樣子的:

一、起始位置為成員資料型別所佔記憶體的整數倍,若不足則不足部分用資料將記憶體填充為該資料型別的整數倍。

二、結構體所佔總記憶體為其成員變數中所佔空間最大資料型別的整數倍。

本人使用的是x86平台,預設對齊係數為8,因此,綜上所述,我們可以對最開始那段**進行分析。

#include

#pragma pack(8)

intmain()

part1;

struct bpart_one;

//對這段**進行分析之後,我們不難發現其中存在一些"空洞",對於這些空洞,程式會自動補零

//於是,其最終結果是16和24也就不難理解了

printf

("%d %d"

,sizeof

(part1)

,sizeof

(part_one));

return0;

}

那麼,這裡又引起了乙個新的問題,記憶體對齊機制是怎麼來的呢?

在計算機中通常會讓cpu從記憶體中一次讀取若干個位元組的資料,而不是一次只讀取乙個位元組的資料,這樣的好處是提高了計算機的效率,然而壞處也顯而易見。

假設cpu一次從記憶體中讀取四個位元組的資料,而現在記憶體中存在乙個char型的資料和乙個int型的資料,如果記憶體不對齊,當cpu第一次跨越四個位元組定址找到了乙個char型的資料,而此時cpu的指向到了int型的中間區域,導致這個int型變數未找到,然後cpu會返回去再次尋找,直到找到該int型變數。這樣不但沒能提高效率,反而增加了cpu的負擔。因此我們通常會在第乙個char型變數後邊填充一部分資料來保證每次定址時位址都是該資料的整數倍,這樣就避免了上述「錯誤」的發生,也就是所謂的記憶體對齊。

結構體在記憶體中對齊

剛剛完成乙個檔案的遷移程式,其中遇到了結構體對齊的問題,所以拿出來說說,與各位博友們分享。我的程式很簡單,就是把之前通過乙個結構體 fwrite 到檔案 a 裡的內容讀出,然後轉給另乙個結構體儲存。程式是簡單,但我擔心的是之前把結構體 fwrite 到檔案 a 的程式對齊結構體規則是怎樣的?一定要知...

結構體在記憶體中的對齊規則

結構體在記憶體中的對齊規則 標籤 儲存 struct 測試iostream c2011 11 15 19 32 4717人閱讀 9 收藏 舉報乙個結構體變數定義完之後,其在記憶體中的儲存並不等於其所包含元素的寬度之和。例一 include using namespace std struct x c...

結構體在記憶體中的儲存方式

乙個結構體變數定義完之後,其在記憶體中的儲存並不等於其所包含元素的寬度之和。例一 include using namespace std struct x s1 int main 在例一中的結構體變數s1定義之後,經測試,會發現sizeof s1 16,其值不等於sizeof s1.a 1 size...