关于指针:golang中的0个长度切片和数组

0 length slices and arrays in golang

试图找出0长度数组和切片在Golang中的行为。想出了两个代码片段(我在某个地方找到了代码,并对其进行了一些修改以使用它)

https://play.golang.org/p/ew2yygvpgc网站

网址:https://play.golang.org/p/jm2p6l6wcg

我从网站上了解到nil数组([]int(nil))的指针值为nil,所以我决定测试它。当然,事实就是这样。我只是对数组的制作和切片感到困惑。它对我来说有意想不到的行为。

我真的对这两个人的行为感到困惑。第一个在我的电脑上和操场上都运行良好。我注意到第一个和最后一个数组的地址总是完全相同的?为什么?

这是为什么?

第二个更奇怪。这是与前一个代码完全相同的代码,只是中间有len/cap的其他代码片段。它不在游乐场上运行,最后一个切片阵列出现错误,由于某种原因,切片的长度为3(在我的计算机上,最后一个切片的长度为0,所有切片的上限为272851504)。但它确实在我的电脑上运行。我注意到用make创建的第一个数组的地址总是小于最后一个数组。它总是不同的,而且有点小(第一个),为什么?数组地址的代码没有更改

另外,make()为什么还要创建一个数组?长度为0的数组如何在内存中查找?


I've noticed that the address of the first and last array is always
the exact same? Why?

Why is this?

您正在将函数中的地址基于函数参数中的切片头。偶然的是,函数每次运行的内存地址都是相同的。另外,作为一个实现细节,当您将原始数据切片为零长度和容量时,它不会使数据指针归零。在这两个函数中,切片头都是被复制的,所以您甚至不需要检查最初的头切片。

第二个例子,您没有正确地读取切片头。如果你想到处玩,你不需要尝试做指针运算,你可以直接得到切片的地址。

1
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&slice))

不过,如果您真的想通过指针算法检查一个切片头,也许这可以更好地说明您需要做什么:https://play.golang.org/p/gl6ntypns8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
func InspectSlice(slice *[]int) {
    // Get the header directly by converting it to a reflect.SliceHeader
    hdr := (*reflect.SliceHeader)(unsafe.Pointer(slice))

    // Create a header for comparison via pointer manipulation
    address := (uintptr)(unsafe.Pointer(slice))
    lenAddr := address + unsafe.Sizeof(address)
    capAddr := lenAddr + unsafe.Sizeof(int(0))

    unsafeHdr := reflect.SliceHeader{
        Data: *(*uintptr)(unsafe.Pointer(address)),
        Len:  *(*int)(unsafe.Pointer(lenAddr)),
        Cap:  *(*int)(unsafe.Pointer(capAddr)),
    }

    fmt.Printf("Real Header:  %#v
", *hdr)
    fmt.Printf("UnsafeHeader: %#v
", unsafeHdr)

}

Also, why does make() even create an array?

make不创建数组,您标记为array的只是一个slice文本。

How does an array of length 0 even look in memory?

看起来什么都不像。它消耗0字节。

在进行零长度切片时,您看到的最有可能是指向全局零值数组的指针。制作一组不同类型的零长度切片,数据指针将全部相同。正如所有空的struct{}和空的nil interface{}都被赋予与优化相同的值一样。这完全是一个实现细节,因为您不需要访问该数据值。当将一个切片切片切回零长度和容量时,运行时也不会将数据指针归零。由于这两个行为,任何切片中的数据指针很少为零。