C記憶體對齊

2021-06-16 19:49:20 字數 1574 閱讀 6626

#include #pragma pack(4)

struct test

;#pragma pack()

int main(void)

上面**在vc6.0環境中編寫,接下來有三個問題:1、加上如**所示的注釋,最終程式輸出多少?2、去掉**中的注釋,最終程式輸出多少?3、去掉#pragma pack(4)和#pragma pack()語句後再執行程式,最終輸出多少?

這裡給出最終答案為:pack(4)=12

對!上面3個問題的答案均一樣!這是為什麼呢?

首先,要明白上述**要說明的乙個問題即是題目所示——「記憶體對齊」,為什麼要進行記憶體對齊呢?根本原因在於cpu訪問資料的效率問題。

對齊跟資料在記憶體中的位置有關。如果乙個變數的記憶體位址正好位於它長度的整數倍,他就被稱做自然對齊。比如在32位cpu下,假設乙個整型變數的位址為0x00000004,那它就是自然對齊的。假設某個整型變數的位址不是自然對齊,比如為0x00000002,則cpu如果取它的值的話需要訪問兩次記憶體,第一次取從0x00000002-0x00000003的乙個short,第二次取從0x00000004-0x00000005的乙個short然後組合得到所要的資料,如果變數在0x00000003位址上的話則要訪問三次記憶體,第一次為char,第二次為short,第三次為char,然後組合得到整型資料。而如果變數在自然對齊位置上,則只要一次就可以取出資料。

回到上面問題,首先對於#pragma pack偽指令語句,其意義在於宣告在其下定義的結構體變數的對齊方式,程式中#pragma pack(4),即表達下面的結構體中的變數以4位元組對齊,而#pragma pack()意思為取消對齊方式,它們是成對出現。當然如果在程式中只使用#pragma pack(4)也是可以的,那就是說明在本原始檔中,該偽指令下的結構均為4位元組對齊方式。至於第3個問題為什麼取消和加上這兩個偽指令結果都一樣,是因為vc6.0編譯器預設為4位元組對齊方式。接下來分析下第1個問題,為什麼會輸出12?首先在x86的32位機器上我們要知道如下資訊:

sizeof(char) = 1;

sizeof(short) = 2;

sizeof(int) = 4;

sizeof(float) = 4;

sizeof(double) = 8;

那接下來就好辦了,在test結構體中定義了4個變數,第乙個int型變數a顯然佔4個位元組,第二個char型變數b佔1個位元組,第三個short型變數c佔2個位元組,第四個char型變數d佔1個位元組。總的位元組數為:4+1+2+1 = 8。不對,明明輸出是12啊?這裡即是記憶體對齊搞的鬼了,假如該結構位址為0x00000000,那麼第乙個變數a的由於佔4個位元組,則其儲存的區域為0x00000000~0x00000003對於第二個變數b,其本身占用1個位元組,其占用的位址為:0x00000004;第三個變數c,其本身占用2個位元組,複核0x00000006%2=0,則其應占用的位址為0x00000006~0x00000007,位址0x00000005需空出;對於第四個變數d,其本身占用1個位元組,則其占用位址為0x00000008,因此總的有效占用位元組為:4+2+2+1=9,為什麼還是不是12呢?注意由於結構與結構之間還存在對齊,因此在該結構體末尾需加上3個位元組補齊,即總的位元組為12。

C 記憶體對齊

vc6.0編譯器對記憶體對齊的管理方式遵循以下兩個原則 1.對於結構體內部變數的對齊方式 變數存放的起始位址相對於結構的起始位址的偏移量 char 偏移量必須為sizeof char 即1的倍數 int 偏移量必須為sizeof int 即4的倍數 float 偏移量必須為sizeof float ...

c 記憶體對齊

一.計算struct的size有兩個原則 pragma pack n n是編譯器的對齊位元組數 1 struct中各成員按照對齊原則 在為當前變數 設為a 分配記憶體時,要參考之前所有變數的偏移量之和 設為d d必須是min n,sizeof a 的倍數,否則編譯器會自動在最後補上缺少的位元組數。2...

C 記憶體對齊

c 中的記憶體對齊 記憶體對齊 在我們的程式中,資料結構還有變數等等都需要占有記憶體,在很多系統中,它都要求記憶體分配的時候要對齊,這樣做的好處就是可以提高訪問記憶體的速度。我們還是先來看一段簡單的程式 程式一 1 include 2 using namespace std 3 4structx1 ...