假设我有这两个结构:
package main
import (
"fmt"
"unsafe"
)
type A struct {
int8
int16
bool
}
type B struct {
int8
bool
int16
}
func main() {
fmt.Println(unsafe.Sizeof(A{}), unsafe.Sizeof(B{})) // 6 4
}
A
的大小为6个字节。但是,B
的大小是4个字节
我认为它与它们在内存中的布局有关,但我不确定我是否理解为什么它的行为如此。
不是编译器可以检测和优化的东西吗? (重新排列字段顺序)
答案 0 :(得分:9)
由于对齐而填充。
The Go Programming Language Specification
对于数字类型,保证以下尺寸:
type size in bytes byte, uint8, int8 1 uint16, int16 2 uint32, int32, float32 4 uint64, int64, float64, complex64 8 complex128 16
保证以下最小对齐属性:
对于任何类型的变量x:unsafe.Alignof(x)至少为1.
对于结构类型的变量x:unsafe.Alignof(x)是x的每个字段f的所有值unsafe.Alignof(x.f)中最大的,但至少是 1。
- 对于数组类型的变量x:unsafe.Alignof(x)与数组元素类型的变量的对齐方式相同。
如果结构或数组类型不包含任何字段(或 元素,分别),大小大于零。二 不同的零大小变量在内存中可能具有相同的地址。
例如,
package main
import (
"fmt"
"unsafe"
)
type A struct {
x int8
y int16
z bool
}
type B struct {
x int8
y bool
z int16
}
func main() {
var a A
fmt.Println("A:")
fmt.Println("Size: ", unsafe.Sizeof(a))
fmt.Printf("Address: %p %p %p\n", &a.x, &a.y, &a.z)
fmt.Printf("Offset: %d %d %d\n", unsafe.Offsetof(a.x), unsafe.Offsetof(a.y), unsafe.Offsetof(a.z))
fmt.Println()
var b B
fmt.Println("B:")
fmt.Println("Size: ", unsafe.Sizeof(b))
fmt.Printf("Address: %p %p %p\n", &b.x, &b.y, &b.z)
fmt.Printf("Offset: %d %d %d\n", unsafe.Offsetof(b.x), unsafe.Offsetof(b.y), unsafe.Offsetof(b.z))
}
游乐场:https://play.golang.org/p/_8yDMungDg0
输出:
A:
Size: 6
Address: 0x10410020 0x10410022 0x10410024
Offset: 0 2 4
B:
Size: 4
Address: 0x10410040 0x10410041 0x10410042
Offset: 0 1 2
您可能正在使用其他语言匹配外部struct
。您可以告诉编译器您想要什么。编译器没有猜测。