Go中struct的内存对齐

直接看代码

var i int32
var ii int64
var b bool
var s string
fmt.Printf("width:%d\n", unsafe.Sizeof(i))  // width:4
fmt.Printf("width:%d\n", unsafe.Sizeof(ii)) // width:8
fmt.Printf("width:%d\n", unsafe.Sizeof(b))  // width:1
fmt.Printf("width:%d\n", unsafe.Sizeof(s))  // width:16

{
   //空结构体的宽度为 0
   type S struct{}
   var ss S
   fmt.Printf("width:%d\n", unsafe.Sizeof(ss)) // width:0
}

{
   type stringStruct struct {
      str unsafe.Pointer // 8
      len int            // 8
   }
   var ss stringStruct
   fmt.Printf("width:%d\n", unsafe.Sizeof(ss)) // width:16
}

//以下涉及内存对齐
// https://dave.cheney.net/2014/03/25/the-empty-struct#comment-2815
{
   type S struct {
      a uint64 // 8
      b uint32 // 4
   }
   var s S
   fmt.Printf("width:%d\n", unsafe.Sizeof(s)) // width:16, not 12
}

{
   type S struct {
      a uint64    // 8
      b uint32    // 4
      c [3]uint32 // 12
   }
   var s S
   fmt.Printf("width:%d\n", unsafe.Sizeof(s)) // width:24
}

{
   type S struct {
      a uint64 // 8
      b bool   //1
   }
   var s S
   fmt.Printf("width:%d\n", unsafe.Sizeof(s)) // width:16, not 9
}
{

   type S struct {
      a uint64    // 8
      b uint32    // 4
      c bool      //1
      d [3]uint32 // 12
   }
   var s S
   fmt.Printf("width:%d\n", unsafe.Sizeof(s)) // width:32, not 25(8+4+1+12), not 28(8+4+4+12)
}

{
   type S struct {
      a uint64 // 8
      b uint32 // 4
      c bool   //1
      d uint32 // 4
   }
   var s S
   fmt.Printf("width:%d\n", unsafe.Sizeof(s)) // width:24
}

 

关键要读懂Russ Cox的这段话:

It’s not true that “a value must be aligned in memory to a multiple of its width.” Each type has another property, its alignment. Alignments are always powers of two. The alignment of a basic type is usually equal to its width, but the alignment of a struct is the maximum alignment of any field, and the alignment of an array is the alignment of the array element. The maximum alignment of any value is therefore the maximum alignment of any basic type. Even on 32-bit systems this is often 8 bytes, because atomic operations on 64-bit values typically require 64-bit alignment.

To be concrete, a struct containing 3 int32 fields has alignment 4 but width 12.

It is true that a value’s width is always a multiple of its alignment. One implication is that there is no padding between array elements.

 

References:

https://dave.cheney.net/2014/03/25/the-empty-struct#comment-2815

https://ijayer.github.io/post/tech/code/golang/20200419_emtpy_struct_in_go

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

*