Struct has different size if the field order is different

leiyonglin
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 A and B have the same fields, but if specified in different order they result in different size. why?

  2. Size of struct C is zero. How much memory is allocated by the system for a := C{}?

Thanks.

icza

1. Struct sizes

TL;DR; (Summary): Different implicit padding will be used if you reorder the fields, and the implicit padding counts towards the size of the struct.

Note that the result depends on the target architecture; results you posted applies when GOARCH=386, but when GOARCH=amd64, sizes of both A{} and B{} will be 24 bytes.

Address of fields of a struct must be aligned, and the address of fields of type int64 must be a multiple of 8 bytes. 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.

Align of int64 is 8 bytes:

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

So in case of A since first field is bool, there is a 7-byte implicit padding after A.a so that A.b which is of type int64 can start on an address that is a multiple of 8. This (that 7-byte padding is needed exactly) is guaranteed as the struct itself is aligned to an address which is a multiple of 8, because that is the largest size of all of its fields. See: 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.

In case of B (and if GOARCH=386 which is your case) there will only be a 3-byte implicit padding after the B.a field of type bool because this field is followed by a field of type int (which has size of 4 bytes) and not int64.

Align of int is 4 bytes if GOARCH=386, and 8 bytes if GOARCH=amd64:

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

Use unsafe.Offsetof() to find out the offsets of fields:

// 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))

Output if GOARCH=386 (try it on the Go Playground):

24 0 8 16
16 0 8 12
0
4

Output if GOARCH=amd64:

24 0 8 16
24 0 8 16
0
8

2. Zero size values

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.

So the spec just gives a hint to use the same memory address but it's not a requirement. But current implementations follow it. That is, no memory will be allocated for values of types having a size of zero, this includes the empty struct struct{} and arrays of zero length, e.g. [0]int, or arrays whose elements has a size of zero (and with arbitrary length).

See this example:

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

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

Output (try it on the Go Playground): All the addresses are the same.

0x21cd7c 0x21cd7c 0x21cd7c 0x21cd7c 0x21cd7c

For an interesting and related topic, read: Dave Cheney: Padding is hard

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Struct has different size after being passed to func

From Dev

Struct has different size after being passed to func

From Dev

Compare two different size vectors of the same struct

From Dev

Compare two different size vectors of the same struct

From Dev

Join two different size cells in the same struct

From Dev

Different size grid with specific order PHP

From Dev

Union Order By using different field SQL Server

From Dev

Input field showing different size in iOS

From Dev

Input field showing different size in iOS

From Dev

UITextField placeholder has different font size

From Dev

compiler showing different errors for unassigned struct object field and property

From Dev

How to display divs in a different order depending on screen size in Bootstrap 3?

From Dev

Render component in different order depending on screen-size (React)

From Dev

How to compare two different size arraylists and check for order of elements

From Dev

How to arrange columns position and order on different screen size on Bootstrap?

From Dev

How to combine three lists of different size in order Python

From Dev

Join table in order to create field with data from different tables

From Dev

Why would the index on a field be a different size depending on if it is ascending or descending in MongoDB

From Dev

Replace a column in Pandas dataframe with another that has same index but in a different order

From Dev

Fixed Layout EPUB where each page has a different size

From Dev

Check whether a record in DB with same ID has different value in field

From Dev

Gson - parsing a json that has different field names and number of fields

From Dev

TextSize for different device with different size?

From Dev

Cursor size is different for different line

From Dev

Different layout for different screen size

From Dev

TextSize for different device with different size?

From Dev

Android - Image coming from web service has different size on different devices

From Dev

Bootstrap Different input size different screen size

From Dev

Packed struct has not the expected size

Related Related

  1. 1

    Struct has different size after being passed to func

  2. 2

    Struct has different size after being passed to func

  3. 3

    Compare two different size vectors of the same struct

  4. 4

    Compare two different size vectors of the same struct

  5. 5

    Join two different size cells in the same struct

  6. 6

    Different size grid with specific order PHP

  7. 7

    Union Order By using different field SQL Server

  8. 8

    Input field showing different size in iOS

  9. 9

    Input field showing different size in iOS

  10. 10

    UITextField placeholder has different font size

  11. 11

    compiler showing different errors for unassigned struct object field and property

  12. 12

    How to display divs in a different order depending on screen size in Bootstrap 3?

  13. 13

    Render component in different order depending on screen-size (React)

  14. 14

    How to compare two different size arraylists and check for order of elements

  15. 15

    How to arrange columns position and order on different screen size on Bootstrap?

  16. 16

    How to combine three lists of different size in order Python

  17. 17

    Join table in order to create field with data from different tables

  18. 18

    Why would the index on a field be a different size depending on if it is ascending or descending in MongoDB

  19. 19

    Replace a column in Pandas dataframe with another that has same index but in a different order

  20. 20

    Fixed Layout EPUB where each page has a different size

  21. 21

    Check whether a record in DB with same ID has different value in field

  22. 22

    Gson - parsing a json that has different field names and number of fields

  23. 23

    TextSize for different device with different size?

  24. 24

    Cursor size is different for different line

  25. 25

    Different layout for different screen size

  26. 26

    TextSize for different device with different size?

  27. 27

    Android - Image coming from web service has different size on different devices

  28. 28

    Bootstrap Different input size different screen size

  29. 29

    Packed struct has not the expected size

HotTag

Archive