C語言位元組對齊的相關筆記

2021-08-21 22:17:25 字數 1668 閱讀 7050

一、概念

對齊跟資料在記憶體中的位置有關。程式中如果乙個變數的記憶體位址正好位於它長度的整數倍,它就被稱做自然對齊。比如在32位cpu下,假設乙個整型變數的位址為0x00000004,那它就是自然對齊的。

二、為什麼要位元組對齊

位元組對齊和cpu的資料訪問效率是有關係的。假設整型變數的位址不是自然對齊,比如為0x00000002,則cpu如果取它的值的話需要訪問兩次記憶體:第一次取從0x00000002——0x00000003的乙個short,第二次取從0x00000004——0x00000005的乙個short,然後組合得到所要的資料。如果變數在0x00000003位址上的話則要訪問三次記憶體,第一次為char,第二次為short,第三次為char,然後組合得到整型資料。如果變數在自然對齊位置上,則只要一次就可以取出資料。

一些系統對對齊要求非常嚴格,如果取未對齊的資料會發生錯誤,舉個例:

char data_buf[5];

char *p = &data_buf[0];

int i = *(int *)p;

在一些risc系統執行時會報segment error,而在x86上就不會出現錯誤,只是效率下降。

三、正確處理位元組對齊

對於標準資料型別,它的位址只要是它的長度的整數倍就行了,而非標準資料型別按下面的原則對齊:

陣列 :按照基本資料型別對齊,第乙個對齊了後面的自然也就對齊了。

聯合體 :按其包含的長度最大的資料型別對齊。

結構體: 結構體中每個資料型別都要對齊。

比如有如下乙個結構體:

struct test;

struct test test_str;

由於在x86下,gcc預設按4位元組對齊,它會在a後面跟c後面分別填充三個和兩個位元組使b和整個結構體對齊。於是我們sizeof(test_str)會得到長度為20,而不是15。

(ps:char a,1個位元組,補上3個所以為4個位元組;int b,4個位元組;char c[10],10個位元組,補上兩個,為12位元組,剛好是4的倍數,所以全部加起來就為4 + 4 + 12 = 20位元組。)

四、__attribute__選項

我們可以按照自己設定的對齊大小來編譯程式,gnu使用__attribute__選項來設定,比如我們想讓剛才的結構按一位元組對齊,我們可以這樣定義結構體

struct test__attribute__ ((aligned (1)));

struct test test_str;

則sizeof(test_str)可以得到大小為15。

上面的定義等同於

struct test__attribute__ ((packed));

struct test test_str;

__attribute__((packed))得變數或者結構體成員使用最小的對齊方式,即對變數是一位元組對齊,對域(field)是位對齊。

五、什麼時候需要設定對齊

在設計不同cpu下的通訊協議時,或者編寫硬體驅動程式時暫存器的結構這兩個地方都需要按一位元組對齊。即使看起來本來就自然對齊的也要使其對齊,以免不同的編譯器生成的**不一樣。

C語言位元組對齊筆記

一 位元組對齊的意義 通過合理的記憶體對齊可以提高訪問效率,有效地節省儲存空間,為使cpu能夠對資料進行快速訪問,資料的起始位址應具有 對齊 特性。比如4位元組資料的起始位址應位於4位元組邊界上,即起始位址能夠被4整除。但是在32位cpu中使用1位元組或者2位元組對齊,會降低變數訪問速度。vc c ...

c語言位元組對齊

現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定型別變數的時候經常在特 定的記憶體位址訪問,這就需要各種型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。基本資料型別自身對齊,也叫自然對齊。就是說...

C語言位元組對齊

一 概念 對齊跟資料在記憶體中的位置有關。如果乙個變數的記憶體位址正好位於它長度的整數倍,他就被稱做自然對齊。比如在32位cpu下,假設乙個整型變數的位址為0x00000004,那它就是自然對齊的。二 為什麼要位元組對齊 需要位元組對齊的根本原因在於cpu訪問資料的效率問題。假設上面整型變數的位址不...