Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why these two structs have different size in the memory?

Suppose I have these two structs:

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
}

Size of A is 6 bytes. however, the size of B is 4 bytes.
I assume that it's related to their layout in the memory, but I'm not sure I understand why it's behave like this.
Isn't something that the compiler can detect and optimize? (rearrange the fields order)

Link to the code

like image 279
mux Avatar asked Feb 12 '18 18:02

mux


People also ask

How much memory do we need for a struct data structure?

In short, machine must allocate enough memory to store all the data fields which included in struct. I will show you some example, After that you will know how to calculate the memory cost in struct data structure. So, How may memories we need for the below data structure? The answer is 32 bytes. Why?

How does the memory configuration shown in Figure 2 affect performance?

Since the memory configuration shown in Figure 2 reduces the number of accesses, it can lead to greater processing efficiency. The data size that a processor uses when accessing memory is called the memory access granularity. Figure 2 depicts a system with four-byte memory access granularity.

How to allocate memory to a struct info5?

Similar to struct Info4, the longest field in struct Info5 is int c, it will take 4 bytes. So machine will use 4 bytes aligned strategy. The field char a, short b can store in the first 4-bytes space, and int c will store in the second one. Finally, machine need to allocate 8 bytes. That is all about struct data structure memory allocation.

How much memory space does a data type take up?

Different data type may takes different memory spaces. We also measure the memory costs by byte instead of bit in machine underlayer. 1 byte usually equals to 8 bits and 1 byte also represented by char data type in C programming language. You can use this simple program to valid it. Char data type take 1 byte.


1 Answers

Padding due to alignment.

The Go Programming Language Specification

Size and alignment guarantees

For the numeric types, the following sizes are guaranteed:

type                                 size in bytes

byte, uint8, int8                     1
uint16, int16                         2
uint32, int32, float32                4
uint64, int64, float64, complex64     8
complex128                           16

The following minimal alignment properties are guaranteed:

  • For a variable x of any type: unsafe.Alignof(x) is at least 1.

  • 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.

  • For a variable x of array type: unsafe.Alignof(x) is the same as the alignment of a variable of the array's element type.

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.


For example,

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

Playground: https://play.golang.org/p/_8yDMungDg0

Output:

A:
Size:    6
Address: 0x10410020 0x10410022 0x10410024
Offset:  0 2 4

B:
Size:    4
Address: 0x10410040 0x10410041 0x10410042
Offset:  0 1 2

You may be matching an external struct, perhaps in another language. It's up to you to tell the compiler what you want. The compiler doesn't guess.

like image 110
peterSO Avatar answered Nov 15 '22 07:11

peterSO