結構體在記憶體中對齊

2021-05-12 17:29:52 字數 2156 閱讀 9892

剛剛完成乙個檔案的遷移程式,其中遇到了結構體對齊的問題,所以拿出來說說,與各位博友們分享。

我的程式很簡單,就是把之前通過乙個結構體 fwrite 到檔案 a 裡的內容讀出,然後轉給另乙個結構體儲存。程式是簡單,但我擔心的是之前結構體 fwrite 到檔案 a 的程式對齊結構體規則是怎樣的?一定要知道它嗎 ? 當然了,如果那個程式結構體是按照 1 對齊寫入的,我的程式結構體是按照 4 對齊讀入,那不就糟了!

struct example1{

char a;

double b;

long l;

struct example2{

char a;

long l;

double b;

大家算算結構體大小,初次接觸的博友可能對答案有點驚訝, vc 編譯, sizeof 後結果分別是: 24 , 16 。 同樣是的結構體,成員換了順序,大小就不同了。其實記憶體對齊有個規則,只要知道了,就 ok 。那麼以下 5 點是關鍵

1.          記憶體對齊與編譯器設定有關,首先要搞清編譯器這個預設值是多少

2.          如果不想編譯器預設的話,可以通過 #pragma pack(n) 來指定按照 n 對齊

3.          每個結構體變數對齊,如果對齊引數 n( 編譯器預設或者通過 pragma 指定 ) 大於該變數所佔位元組數 (m) ,那麼就按照 m 對齊,記憶體偏移後的位址是 m 的倍數,否則是按照 n 對齊,記憶體偏移後的位址是 n 的倍數。也就是最小化長度規則

4.          結構體總大小 : 對齊後的長度必須是成員中最大的對齊引數的整數倍。最大對齊引數是從第三步得到的。

5.          補充:如果結構體 a 中還要結構體 b ,那麼 b 的對齊方式是選它裡面最長的成員的對齊方式

所以計算結構體大小要走三步,首先確定是當前程式按照幾對齊 ( 參照 1 , 2 點 ) ,接著計算每個結構體變數的大小和偏移 ( 參照 3 , 5) ,最後計算結構體總大小(參照 4 )。

先算算 example1 吧,假設編譯器是以 16 對齊的

1 .確定按照幾對齊 : 16;

2 .確定每個成員的偏移: a 佔乙個位元組, 16>1, 按照 1 對齊,起始位置 0 , 0%1 = 0 ,那麼 a 就存在 0 位置; b 佔 8 個位元組, 16>8 ,按照 8 對齊,起始位置就不能是 1 了,因為要按照 8 對齊,所以最近的偏移起始位置是 8 , 8%8 =0, 那麼 b 就存在位置 8-15 的位置; l 佔 4 個位元組, 16>4 ,按照 4 對齊,起始位置 16 , 16%4=0 ,那麼 l 就存在位置 16-19 的位置。所以結構體從 0 到 19 一共占用 20 個位元組

3 .結構體總大小:成員中最大的對齊引數是 b 的 8 對齊,所以 20 % 8!=0, 24 剛好。

真的很搞!同理計算 example2 應該是 16 ;

再舉個結構體巢狀的例子吧,

#pragma pack(push)

#pragma pack(8)

struct test1{

int a;

char b;

int c[20]

long l;

struct test2{

char a1;

char a2;

struct test1 t1;

double b1;

#pragma pack(pop)

先計算 test1, 8 對齊, a 占用 0-3 , b 占用 4 , c 占用 8 - 87 , l 占用 88 - 91 ,一共 92 個位元組。成員中最大的對齊引數是 int 了 92%4=0;

再計算 test2, a1z 占用 0 , a2 占用 1 , t1 呢, 92%2!=0, 2-92 , b1 佔 96 到 103 ;一共 104 個位元組,成員中最大的對齊引數是 double 了 104%8=0; 所以是 104.

那關於我文章開頭提到的那個檔案轉換,我現在只要知道原始程式是按照什麼對齊的,然後在新程式中指定按照幾對齊就可以了,哈哈!    

有的地方有遺漏,請各位指正!

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

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

結構體對齊(記憶體對齊

有的時候,在腦海中停頓了很久的 顯而易見 的東西,其實根本上就是錯誤的。就拿下面的問題來看 structt 使用sizeof t 將得到什麼樣的答案呢?要是以前,想都不用想,在32位機中,int是4個位元組,char是1個位元組,所以t一共是5個位元組。實踐出真知,在vc6中測試了下,答案確實8個位...

記憶體對齊 結構體對齊

現在已知32位機器上各種資料型別的長度如下 char 1 有符號無符號同 short 2 有符號無符號同 int 4 有符號無符號同 long 4 有符號無符號同 float 4 double 8 重要規則 1,複雜型別中各個成員按照它們被宣告的順序在記憶體中順序儲存,第乙個成員的位址和整個型別的位...