1. 程式人生 > 其它 >float佔幾個位元組_C語言位元組對齊

float佔幾個位元組_C語言位元組對齊

技術標籤:float佔幾個位元組vc++64位系統下long的長度為4個位元組

什麼是位元組對齊

在C語言中,結構是一種複合資料型別,其構成元素既可以是基本資料型別(如int、long、float等)的變數,也可以是一些複合資料型別(如陣列、結構、聯合等)的資料單元。在結構中,編譯器為結構的每個成員按其自然邊界(alignment)分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存,第一個成員的地址和整個結構的地址相同。

為了使CPU能夠對變數進行快速的訪問,變數的起始地址應該具有某些特性,即所謂的”對齊”. 比如4位元組的int型,其起始地址應該位於4位元組的邊界上,即起始地址能夠被4整除.

位元組對齊作用

位元組對齊的作用不僅是便於cpu快速訪問,同時合理的利用位元組對齊可以有效地節省儲存空間。

對於32位機來說,4位元組對齊能夠使cpu訪問速度提高,比如說一個long型別的變數,如果跨越了4位元組邊界儲存,那麼cpu要讀取兩次,這樣效率就低了。但是在32位機中使用1位元組或者2位元組對齊,反而會使變數訪問速度降低。所以這要考慮處理器型別,另外還得考慮編譯器的型別。在vc中預設是4位元組對齊的,GNU gcc 也是預設4位元組對齊。

位元組對齊的方式

1.使用偽指令#pragma pack

  • 使用偽指令#pragma pack (n),C編譯器將按照n個位元組對齊。

  • 使用偽指令#pragma pack (),取消自定義位元組對齊方式。

需要注意的是,#pragma pack

結構體對齊規則舉例:

摘自:https://blog.csdn.net/lime1991/article/details/44536343

結構體中各個成員按照它們被宣告的順序在記憶體中順序儲存。

1)將結構體內所有資料成員的長度值相加,記為sum_a;
2)將各資料成員記憶體對齊,按各自對齊模數而填充的位元組數累加到和sum_a上,記為sum_b。對齊模數是【該資料成員所佔記憶體】與【#pragma pack指定的數值】中的較小者。
3)將和sum_b向結構體模數對齊,該模數是【#pragma pack指定的數值】、【未指定#pragma pack時,系統預設的對齊模數4位元組】和【結構體內部最大的基本資料型別成員】長度中數值較小者。結構體的長度應該是該模數的整數倍。

3.1 基本資料型別所佔記憶體大小

0edd0cfe7dbdaefc56522a39569dfca9.png

以下例子均按32bit編譯器處理。

3.2 Test1

#pragmapack(4)structTest1{  char c;  short sh;  int a;  float f;  int *p;  char *s;  double d;};

上述結構體總共佔28Bytes。

  • c的偏移量為0,佔1個Byte。

  • sh佔2個Byte,它的對齊模數是2(2<4,取小者),存放起始地址應該是2的整數倍,因此c後填充1個空字元,sh的起始地址是2。

  • a佔4個Byte,對齊模數是4,因此接在sh後存放即可,偏移量為4。

  • f佔4個位元組,對齊模數是4,存放地址是4的整數倍,起始地址是8。

  • p,s的起始地址分別是12, 16。

  • d佔8個位元組,對齊模數是4(4<8),d從偏移地址為20處存放。存放後結構體佔28個位元組,是4的整數倍不用補空字元。

46f72246969cb7a8ed1653774e272984.png

2. 使用__attribute__屬性

  • __attribute((aligned (n))),讓所作用的結構成員對齊在n位元組自然邊界上。如果結構中有成員的長度大於n,則按照最大成員的長度來對齊。

  • __attribute__ ((packed)),取消結構在編譯過程中的優化對齊,按照實際佔用位元組數進行對齊。

typedef struct{    uint8_t  len;    uint8_t  is_need_update;    uint8_t  data[3];    uint64_t padding;} v_keys_stg __attribute__((aligned(8)));static v_keys_stg  g_vk_data = {0};static v_keys_stg  g_vm_data = {0};app.map檔案SymbolNameaddrtype     size    objectg_vk_data     0x00211a30   Data     16  key_handle.o(.bss)g_vm_data     0x00211a40   Data     16  key_handle.o(.bss)

注意:如果結構體中的成員全部都是uint8_t,起始地址會根據

__attribute__設定的值進行對齊變化,但是實際的佔用的size大小沒有變化的;