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不创建数组,您标记为
How does an array of length 0 even look in memory?
号
看起来什么都不像。它消耗0字节。
在进行零长度切片时,您看到的最有可能是指向全局零值数组的指针。制作一组不同类型的零长度切片,数据指针将全部相同。正如所有空的