c 的位元組對齊很重要,因為c 支援指標運算。在golang 裡面一般是慎用指標運算的,所以,這部分很少用,但是有些場景為了效能不得不用到指標運算,這個時候,知道golang 的記憶體分配就很重要了。但是基本很少有相關的參考資料,很多也不靠譜,這裡借鑑c 的規則驗證golang 的記憶體對齊規則。
首先,有個問題,為什麼 函式 unsafe.offsetof(a.a1) 的引數怪怪的,非得把結構體型別也傳進去?
c中位元組對齊規則:
1、資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員的位址必須是它本身大小或對齊引數兩者中較小的乙個的倍數。
2、整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,整體長度必須是對齊引數和結構體最長的元素長度中較小的乙個的倍數。
package main
import (
"fmt"
"unsafe"
)type a struct
// 4 / min(8, 2) 大小為4
type b struct
// [0, 1] + 2 + [3, 10]=11 / min(8, 8) 不盡,不符合規則2,大小為16,記憶體圓整
type c struct
// 16/ min(8, 8) 大小為16
type d struct
// 17 /min(8, 8), 大小為17,資料圓整,padding 為24 /8 = 3能整除
func main()
var b = b{}
var c = c{}
var d = d{}
// size of a = 4
// a1: 1 位元組 + 1 位元組padding
// a2: 2 位元組
fmt.printf("a.a1 offset %v \n", unsafe.offsetof(a.a1))
fmt.printf("a.a2 offset %v \n", unsafe.offsetof(a.a2))
fmt.printf("size of a = %d\n", unsafe.sizeof(a))
// size of b = 16
// b1: 2 位元組
// b2: 1 位元組 + 5 位元組padding
// b3: 8 位元組
fmt.printf("b.b1 offset %v \n", unsafe.offsetof(b.b1))
fmt.printf("b.b2 offset %v \n", unsafe.offsetof(b.b2))
fmt.printf("b.b3 offset %v \n", unsafe.offsetof(b.b3))
fmt.printf("size of b = %d\n", unsafe.sizeof(b))
// size of c = 16
// c1: 1 位元組 + 3 位元組padding
// c2: 4 位元組
// c3: 8 位元組
fmt.printf("c.c1 offset %v \n", unsafe.offsetof(c.c1))
fmt.printf("c.c2 offset %v \n", unsafe.offsetof(c.c2))
fmt.printf("c.c3 offset %v \n", unsafe.offsetof(c.c3))
fmt.printf("size of c = %d\n", unsafe.sizeof(c))
// size of d = 24
// d1: 4位元組 + 4位元組padding
// d2: 8 位元組
// d3: 1位元組 + 7 位元組padding
// d1的尾部padding的原因是要保證是結構體自身也是對齊的
// 因為這樣可以確保實現結構體陣列時候裡面每個元素也是對齊的
fmt.printf("d.d1 offset %v \n", unsafe.offsetof(d.d1))
fmt.printf("d.d2 offset %v \n", unsafe.offsetof(d.d2))
fmt.printf("d.d3 offset %v \n", unsafe.offsetof(d.d3))
fmt.printf("size of d = %d\n", unsafe.sizeof(d))
// 由於有補齊,兩個結構體即便有相同型別的字段,但前後順序不同也可導致size不同
}
發現c 的記憶體分配規則其實和golang 是一致的。最後其實這裡是不是一致對於使用來說不會有太大影響,因為指標計算,轉換之前,會提前用offsetof 計算,這個偏移,golang 會將padding 都算進去, 和c 用的時候不太一樣,這樣做,不會出錯。
這裡特別提下就是不同平台和對齊引數的不一致,會導致結果完全不同。
記憶體位元組對齊
一 什麼是對齊,以及為什麼要對齊 1.現代計算機中記憶體空間都是按照byte劃分的,從理論上講似乎對任何型別的變數的訪問可以從任何位址開始,但實際情況是在訪問特定變數的時候經常在特定的記憶體位址訪問,這就需要各型別資料按照一定的規則在空間上排列,而不是順序的乙個接乙個的排放,這就是對齊。2.對齊的作...
記憶體位元組對齊
之前對記憶體位元組序知道一些,但是一直沒有系統的學習過,導致有時候還是說不清楚的,今天在網上查到一些自己,學習了下,並驗證了,特意給大家分享下,希望對大家能有幫助 總的來說就三條原則 在沒有 pragma pack巨集的時候 1 資料成員對齊規則,在結構體 struct 中,第乙個資料成員從0開始,...
記憶體位元組對齊
在c語言面試和考試中經常會遇到記憶體位元組對齊的問題。今天就來對位元組對齊的知識進行小結一下。首先說說為什麼要對齊。為了提高效率,計算機從記憶體中取資料是按照乙個固定長度的。以32位機為例,它每次取32個位,也就是4個位元組 每位元組8個位,計算機基礎知識,別說不知道 位元組對齊有什麼好處?以int...