gpt4 book ai didi

memory - 如果字段顺序不同,则结构具有不同的大小

转载 作者:IT王子 更新时间:2023-10-29 00:49:15 25 4
gpt4 key购买 nike

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{}))
}
  1. Struct AB 具有相同的字段,但如果以不同的顺序指定,它们会导致不同的大小。为什么?

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

谢谢。

最佳答案

1。结构尺寸

长话短说; (总结): 如果您对字段重新排序,将使用不同的隐式填充,并且隐式填充计入 struct 的大小。 .

请注意,结果取决于目标架构;您发布的结果适用于 GOARCH=386 ,但是当GOARCH=amd64 , 两者的尺寸 A{}B{}将是 24 个字节。

struct的字段地址必须对齐,int64类型的字段地址必须是 8 字节的倍数。 Spec: Package unsafe :

Computer architectures may require memory addresses to be aligned; that is, for addresses of a variable to be a multiple of a factor, the variable's type's alignment. The function Alignof takes an expression denoting a variable of any type and returns the alignment of the (type of the) variable in bytes.

对齐int64是8个字节:

fmt.Println(unsafe.Alignof((int64(0)))) // Prints 8

所以在 A 的情况下因为第一个字段是 bool , A.a 之后有一个 7 字节的隐式填充这样A.b这是类型 int64可以从 8 的倍数的地址开始。这(正好需要 7 字节填充)保证为 struct本身与 8 的倍数的地址对齐,因为这是其所有字段中最大的大小。请参阅:Spec: Size alignment guarantees:

For a variable x of struct type: unsafe.Alignof(x) is the largest of all the values unsafe.Alignof(x.f) for each field f of x, but at least 1.

如果是B (如果 GOARCH=386 是你的情况)在 B.a 之后只会有一个 3 字节的隐式填充。类型字段 bool因为这个字段后面跟着一个 int 类型的字段(大小为 4 个字节)而不是 int64 .

对齐int如果 GOARCH=386 是 4 个字节, 如果 GOARCH=amd64 则为 8 个字节:

fmt.Println(unsafe.Alignof((int(0))))   // Prints 4 if GOARCH=386, and 8 if GOARCH=amd64

使用 unsafe.Offsetof() 找出字段的偏移量:

// output 24
a := A{}
fmt.Println(unsafe.Sizeof(a),
unsafe.Offsetof(a.a), unsafe.Offsetof(a.b), unsafe.Offsetof(a.c))

// output 16
b := B{}
fmt.Println(unsafe.Sizeof(b),
unsafe.Offsetof(b.b), unsafe.Offsetof(b.a), unsafe.Offsetof(b.c))

// output 0
fmt.Println(unsafe.Sizeof(C{}))

var i int
fmt.Println(unsafe.Sizeof(i))

输出如果GOARCH=386 (在 Go Playground 上试试):

24 0 8 16
16 0 8 12
0
4

输出如果GOARCH=amd64 :

24 0 8 16
24 0 8 16
0
8

2。零尺寸值

Spec: Size alignment guarantees:

A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.

所以规范只是提示使用相同的内存地址,但这不是必需的。但是当前的实现遵循它。也就是说,不会为大小为零的类型的值分配内存,这包括空结构 struct{}和零长度数组,例如[0]int ,或元素大小为零(且具有任意长度)的数组。

看这个例子:

a := struct{}{}
b := struct{}{}
c := [0]int{}
d := [3]struct{}{}

fmt.Printf("%p %p %p %p %p", &a, &b, &c, &d, &d[2])

输出(在 Go Playground 上尝试):所有地址都相同。

0x21cd7c 0x21cd7c 0x21cd7c 0x21cd7c 0x21cd7c

有关有趣且相关的主题,请阅读:Dave Cheney: Padding is hard

关于memory - 如果字段顺序不同,则结构具有不同的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34219232/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com