Почему Go выровненный 4-байтовый структурный адрес после мода 8 равен 4 в 64-битной арке? - PullRequest
0 голосов
/ 11 февраля 2020

Когда я изучаю код в syn c .WaitGroup, я замечаю, что в WaitGroup используется поле state1 ([3] uint32), чтобы принять 64-битный выровненный указатель для состояния atomi c store.

Например:

// https://github.com/golang/go/issues/19149
type WaitGroup struct {
    noCopy noCopy
    state1 [3]uint32
}

// state returns pointers to the state and sema fields stored within wg.state1.
func (wg *WaitGroup) state() (statep *uint64, semap *uint32) {
    if uintptr(unsafe.Pointer(&wg.state1))%8 == 0 {
        return (*uint64)(unsafe.Pointer(&wg.state1)), &wg.state1[2]
    } else {
        return (*uint64)(unsafe.Pointer(&wg.state1[1])), &wg.state1[0]
    }
}

Но когда я проверяю это на ма c и linux, в 64-битной системе первый выделенный 4-байтовый выровненный адрес структуры данных отображается после того, как мод 8 равен 4 , в то время как на 32-битных системах это 0 .

Мне интересно, как это гарантировано в golang?

коде здесь: https://play.golang.org/p/oiZMHd2c0I6

// 32-bit system:
// GOARCH=386 go run main.go
// 0 4 0 //why first address mod 8 is 0

// 64-bit system:
// go run main.go
// 4 0 4 //why first address mod 8 is 4

Обновлено: с адресом ответа @ Renat, адрес переменной не гарантируется. Вывод может не состоять.

1 Ответ

1 голос
/ 11 февраля 2020

С golang .org :

Для компьютерных архитектур может потребоваться выравнивание адресов памяти; то есть для адресов переменной, кратных фактору, выравнивание типа переменной . Функция Alignof принимает выражение, обозначающее переменную любого типа, и возвращает выравнивание (тип) переменной в байтах.

Так, учитывая, что Alignof(c) равно 4, оно будет выровнен по 4, необязательно по 8 байт.

При создании другого объекта M

var c = M{}
var d = M{}
println(
    unsafe.Sizeof(c),
    unsafe.Alignof(c),
    uintptr(unsafe.Pointer(&c.x))%8,
)
println(
    "    ",
    uintptr(unsafe.Pointer(&d.x))%8,
)

я получил:

12 4 4
     0
...