union 與struct的空間計算

2021-09-06 12:50:02 字數 2891 閱讀 4464

一、x86

總體上遵循兩個原則:

說明:假定結構體是從位址0開始依次存放各個變數的

struct

s1 student;

詳細解釋:sizeof()用法彙總

為什麼會有這樣的規定呢?

這一定與處理器的字長有關(處理器一次訪問資料的寬度)和編譯器對結構體變數的處理有關。不幸的是,本人對x86架構不甚熟悉,只能借助與arm結構來說明這個問題。

二、arm

總體上遵循兩個原則:

struct

s1 student;

為什麼會有這樣的規定呢?

這一定與處理器的字長有關(處理器一次訪問資料的寬度),所以必須先將arm的字長,實際上涉及的內容是load/stort儲存方式。arm字長是32位,4個位元組。也就是說,無論如何它都要使用32位資料匯流排(雖然它也支援位元組/半字傳送)。

ldr指令

什麼意思呢?看程式你就知道了。

int型別變數的儲存

area    init,code,readonly

import main

entry

_entry

ldr r0,=0x12345678

ldr r1,=0x1000

str r0,[r1]

ldr r2,[r1] ;r2=0x12345678

ldr r2,[r1,#

1] ;r2=0x78123456不對齊發生旋轉

ldr r2,[r1,#2] ;r2=0x56781234

bl main

end

試想,倘若我們定義了乙個int變數,值為0x12345678,按照小端格式在0x1000、0x1001、0x1002、0x1003,依次存放的資料是0x78、0x56、0x34、0x12,而我們再從這兒(0x1000)取的時候,還是0x12345678。

假設我們按照小端格式存但是沒有對齊(4位元組對齊),在0x1001、0x1002、0x1003、0x1004,依次存放0x78、0x56、0x34、0x12,再假設0x1000單元存了乙個0xab。那麼我們再從這兒(0x1001)取的時候,取出來的就是0xab345678,顯然讀到的不是之前存的資料。

就算是,有乙個非常聰明的編譯器,知道如果沒有對齊存放的話,將來取的時候,要從0x1001、0x1002、0x1003取一部分(一條指令),然後再從0x1004取一部分(一條指令),最後整合(好幾條指令),這樣的工作實在是麻煩,編譯器的效率是極低的。

所以,最好的辦法就是一開始存資料的時候,就根據其型別合適的對齊存放。例如int變數,就給它分配到能被4整除的位址上(實際上在它之前的儲存空間大小就是4的倍數),而不要將其分配在不能被4整除的位置上。

倘若是double型別的變數,實在無可奈何,存的時候只有分兩次存,讀的時候分兩次讀,這也是32位機最快的方法。倘若沒有對齊,不知道要在訪問時折騰多少次。也就是說,把double型別(其實還有其他》4位元組的型別)都是放在以4為倍數的位址上。

char型變數的儲存

至於char型變數,是沒什麼要求的。

ldr r0,=0x12345678

ldr r1,=0x1000

str r0,[r1]

ldrb r2,[r1] ;r2=0x00000078

ldrb r2,[r1,#

1] ;r2=0x00000056

ldrb r2,[r1,#2] ;r2=0x00000034

ldrb指令,你從哪個地方讀,就返回你想要的值,不會發生什麼移位旋轉的問題。所以,你把乙個char型變數,放在任意位置都行,ldrb指令都能準確無誤的將其取出。

short變數的儲存

還有short變數,這個也是有說唱的。情況也有些複雜,但沒有ldr指令那麼複雜。 

ldr r0,=0x12345678

ldr r1,=0x1000

str r0,[r1]

ldrh r2,[r1] ;r2=0x00005678

ldrh r2,[r1,#

1] ;r2=0x00005678不對齊讀的還是0x10000的內容

ldrh r2,[r1,#

2] ;r2=0x00001234

試想,倘若我們定義了乙個short變數,值為0x5678,按照小端格式在0x1000、0x1001,依次存放的資料是0x78、0x56,而我們再從這兒(0x1000)取的時候,還是0x00005678。

假設我們按照小端格式存但是沒有對齊(2位元組對齊),在0x1001、0x1002 ,依次存放0x78、0x56,再假設0x1000單元存了乙個0xab。那麼我們再從這兒(0x1001)取的時候,取出來的就是0x000078ab,顯然讀到的不是之前存的資料。

所以在儲存short變數時,是存在以2為倍數的位址上。

回到正題

由上可知,我們知道了變數在儲存過程中對位址的限制。通常,這些非常底層的東西,程式設計師是無需知道的。只不過,當用到struct結構體時,會把這個問題翻出來。

結構體變數的成員是按次序在記憶體中排放,排放時候也需要遵從上邊的限制。現在,那兩條規則的原因就是這樣了。

結論

不同架構的處理器對應著一定的編譯器,這些不同的編譯器對struct變數的處理是不一樣的。

union 與struct的空間計算

總體上遵循兩個原則 1 整體空間是 占用空間最大的成員 的型別 所佔位元組數的整倍數 2 資料對齊原則 記憶體按結構成員的先後順序排列,當排到該成員變數時,其前面已擺放的空間大小必須是該成員型別大小的整倍數,如果不夠則補齊,以此向後類推。注意 陣列按照單個變數乙個乙個的擺放,而不是看成整體。如果成員...

struct和union在記憶體中占用空間大小的計算

資料型別 32位系統 64位系統 bool 1位元組1位元組 char 1位元組1位元組 short 2位元組2位元組 int4位元組 4位元組long 4位元組8位元組 long long 8位元組8位元組 float 4位元組4位元組 double 8位元組8位元組 long double 12...

union 和 struct 的區別與聯絡

union 共用體 構造資料型別,也叫聯合體 用途 使幾個不同型別的變數共佔一段記憶體 相互覆蓋 struct 結構體 是一種構造型別 用途 把不同的資料組合成乙個整體 自定義資料型別 主要區別 1.struct和union都是由多個不同的資料型別成員組成,但在任何同一時刻,union中只存放了乙個...