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 基本資料型別所佔記憶體大小
以下例子均按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的整數倍不用補空字元。
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大小沒有變化的;