對齊就是要滿足儲存變數的起始位址與對齊大小餘數為0。
對於union,分兩步:先算union對齊大小,對齊的大小是取決於union成員中位元組對齊最大的那個;再算union實際分配的空間,而分配給union的實際大小不僅要滿足是對齊大小的整數倍,同時要滿足實際大小不能小於最大成員的大小。
如:union u1
;成員a是char陣列,對齊大小為1位元組,成員b是int,對齊大小為4位元組,所以u1對齊大小為4位元組;分配給u1的實際大小既要是4位元組的整數倍,又要不小於最大成員a的大小,即位4的整數倍又要大於9,所以實際分配的空間為12位元組。
若其中的int b改為double,則對齊為8,大小為16。
複雜一點的情況:
union u2
;對齊是double的大小,為8,大小應當為是16。
對於stuct,分三步:先算struct的對齊大小,對齊的大小也是取決於struct成員中位元組對齊最大的那個;然後根據每個成員的對齊大小對齊每個成員算出分配的空間;最後算出struct實際分配的空間,在滿足對齊每個成員的基礎上,滿足是struct
對齊大小的整數倍。
struct s1
;對齊大小為8,對齊每個成員後大小為24,正好是8的整數倍,所以實際分配的大小就為24。
struct s2
;s1對齊大小為8,u1對齊大小為4,因此s2的對齊大小8,體積大小為大於24+12且要為8的倍數,結果為40。
這裡所說的union和struct的對齊,是指其作為其他複雜物件中的元素的時候要求的對齊,對於本身大小的計算並沒有關係。本身的大小只和其所包含的基本元素的對齊有關係。
struct的大小和內部元素的排列是有很大關係的,而union裡元素排序沒關係,因此在使用struct的時候,安排好元素的位置,可以減少結構體的大小。
如:struct s3
;根據之前的原則,因為c需要4位元組對齊,因此b之後會有3位元組空餘。所以1+3(空餘)+4+13=21,要求為4的倍數,則為24。
若更改為
struct s4
則c之前會空餘2位元組,所以1+13+2+4=20,並且已經為4的倍數,所以大小就是20。
關於#pragma pack(),該標示用於重新指定對齊的大小,當元素的對齊大於指定的對齊大小的時候,成員和整個物件的對齊大小會採用相對較小的。
如:union u3
;該union的對齊為8,大小為16(大於9且為8的倍數)。
若加上#pragma pack(4)// pack(0)會採用預設的位元組(4)
則對於u3中的基本元素b,其對齊由原來的8變為4,而a的對齊仍然是1,則u3的對齊為4,大小為12。
當然u3的對齊也由8變成了4。
位域位元組對齊
使用位域的主要目的是壓縮儲存,其大致規則為 1 如果相鄰位域字段的型別相同,且其位寬之和小於型別的sizeof大小,則後面的字段將緊鄰前乙個字段儲存,直到不能容納為止 2 如果相鄰位域字段的型別相同,但其位寬之和大於型別的sizeof大小,則後面的字段將從新的儲存單元開始,其偏移量為其型別大小的整數...
記憶體對齊和位域
結構體的記憶體結構 當我們解決實際問題時,我們會發現編譯器提供給我們的內建型別其實不夠用,沒有辦法用同一種型別儲存多種型別的資料,c語言中有自己的自定義型別,比如結構 位域 聯合 列舉 typedef關鍵字等。下面我就簡單的介紹一下結構和位域。結構 在乙個名字下的一組變數,有時也稱為聚集資料型別。位...
記憶體對齊以及位域
首先我們大家先思考乙個問題,為什麼編譯器會有記憶體對齊這種東西呢?原因有二 一.平台原因 某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。二.效能原因 如果訪問的是未對齊的記憶體,處理器需要做兩次記憶體訪問 如果記憶體對齊,則處理器只需要做一次記憶體訪問。許多計算機系統對基本型別...