Memory 如果字段顺序不同,则结构的大小也不同

Memory 如果字段顺序不同,则结构的大小也不同,memory,struct,go,padding,sizeof,Memory,Struct,Go,Padding,Sizeof,结构A和B具有相同的字段,但如果按不同的顺序指定,则会导致不同的大小。为什么? 结构C的大小为零。系统为a:=C{}分配了多少内存 谢谢。1。结构尺寸 TL;博士(摘要):如果对字段进行重新排序,将使用不同的隐式填充,并且隐式填充将计入结构的大小 注意,结果取决于目标体系结构;当GOARCH=386时,您发布的结果适用,但当GOARCH=amd64时,A{}和B{}的大小都将为24字节 结构的字段地址必须对齐,类型为int64的字段地址必须是8字节的倍数 计算机体系结构可能需要对齐内存地址;也就

结构
A
B
具有相同的字段,但如果按不同的顺序指定,则会导致不同的大小。为什么?

  • 结构
    C
    的大小为零。系统为
    a:=C{}
    分配了多少内存

  • 谢谢。

    1。结构尺寸 TL;博士(摘要):如果对字段进行重新排序,将使用不同的隐式填充,并且隐式填充将计入结构的大小

    注意,结果取决于目标体系结构;当
    GOARCH=386
    时,您发布的结果适用,但当
    GOARCH=amd64
    时,
    A{}
    B{}
    的大小都将为24字节

    结构的字段地址必须对齐,类型为
    int64
    的字段地址必须是8字节的倍数

    计算机体系结构可能需要对齐内存地址;也就是说,如果变量的地址是因子的倍数,则变量的类型的对齐方式。函数
    Alignof
    采用表示任何类型变量的表达式,并以字节为单位返回(变量类型)的对齐方式

    int64的对齐长度为8字节:

    package main
    
    import (
        "fmt"
        "unsafe"
    )
    
    type A struct {
        a bool
        b int64
        c int
    }
    
    type B struct {
        b int64
        a bool
        c int
    }
    
    type C struct {
    }
    
    func main() {
        // output 24
        fmt.Println(unsafe.Sizeof(A{}))
    
        // output 16
        fmt.Println(unsafe.Sizeof(B{}))
    
        // output 0
        fmt.Println(unsafe.Sizeof(C{}))
    }
    
    因此,在
    A
    的情况下,由于第一个字段是
    bool
    ,因此
    A.A
    之后有一个7字节的隐式填充,因此
    A.b
    类型为
    int64
    的地址可以从8的倍数开始。这(需要精确的7字节填充)是有保证的,因为
    结构本身与地址对齐,地址是8的倍数,因为这是所有字段的最大大小。见:

    对于结构类型的变量
    x
    unsafe.Alignof(x)
    unsafe.Alignof(x.f)
    的每个字段
    f
    ,但至少
    1

    B
    的情况下(如果
    GOARCH=386
    这是您的情况),类型为
    bool
    B.a
    字段后面将只有一个3字节的隐式填充,因为该字段后面是
    int
    类型的字段(大小为4字节),而不是
    int64

    如果
    GOARCH=386
    ,int
    的对齐长度为4个字节,如果
    GOARCH=amd64
    ,对齐长度为8个字节:

    fmt.Println(unsafe.Alignof((int64(0)))) // Prints 8
    
    24 0 8 16
    16 0 8 12
    0
    4
    
    用于查找字段的偏移量:

    fmt.Println(unsafe.Alignof((int(0))))   // Prints 4 if GOARCH=386, and 8 if GOARCH=amd64
    
    如果GOARCH=386,则输出(请在上尝试):

    如果GOARCH=amd64,则输出:

    fmt.Println(unsafe.Alignof((int64(0)))) // Prints 8
    
    24 0 8 16
    16 0 8 12
    0
    4
    
    2.零尺寸值

    如果结构或数组类型不包含大小大于零的字段(或元素),则其大小为零两个不同的零大小变量在内存中可能具有相同的地址。

    因此,规范只是给出了使用相同内存地址的提示,但这不是一个要求。但目前的实现遵循这一原则。也就是说,不会为大小为零的类型的值分配内存,这包括空结构
    struct{}
    和长度为零的数组,例如
    [0]int
    ,或元素大小为零(且具有任意长度)的数组

    请参见此示例:

    24 0 8 16
    24 0 8 16
    0
    8
    
    输出(在上尝试):所有地址都相同

    a := struct{}{}
    b := struct{}{}
    c := [0]int{}
    d := [3]struct{}{}
    
    fmt.Printf("%p %p %p %p %p", &a, &b, &c, &d, &d[2])
    


    有关有趣且相关的主题,请阅读:

    2。是否需要为元数据分配一些内存,如type info.structs不包含type info(并且除了字段之外没有大小开销),这都由编译器处理。但是,接口包含类型和值。