在Java中,二维数组是多维数组.这意味着那些一维数组在内存中不是连续的。
相反,在C中,二维数组实际上是尺寸为total_row * total_column的一维数组。因为Go语言使用了C语言中的许多概念。
所以我的问题是:二维数组在Go中的内存表示看起来像C还是Java?
发布于 2016-09-18 18:59:12
列阵
引用规范:数组类型:的话
数组类型通常是一维,但可以组成多维类型.
这是你的答案明白明了。但是答案不仅仅是因为数组是Go中的值,它们也不是像片一样的描述符(头)。
参见这个简单的例子:
x := [5][5]byte{}
fmt.Println(&x[0][3])
fmt.Println(&x[0][4])
fmt.Println(&x[1][0])输出(在围棋游乐场上尝试):
0x10432203
0x10432204
0x10432205如您所见,为数组分配和使用的内存是连续的:第二行从一个内存地址开始,该地址是第一行的最后一个元素的地址的后继。
检查数组的大小:
fmt.Println(unsafe.Sizeof([4][6]int{})) // 96
fmt.Println(unsafe.Sizeof([6][4]int{})) // 96如果您切换行和列并不重要,它的大小是相同的。
切片
在片的情况下也是如此:多维片就是片的片。规范:切片类型:
片是基础数组的连续段的描述符,并提供对该数组中元素的编号序列的访问。 ..。 像一样,片总是一维的,但可能是用来构造高维对象的。。
切片是描述符,片头包含指向基础(支持)数组的元素的指针、长度和容量。因此,从内存使用的角度来看,总片的数量很重要。
参见此示例:
x := make([][]byte, 2)
for i := range x {
x[i] = make([]byte, 1000)
}
fmt.Println(len(x), len(x)*len(x[0]))
y := make([][]byte, 1000)
for i := range y {
y[i] = make([]byte, 2)
}
fmt.Println(len(y), len(y)*len(y[0]))输出(在围棋游乐场上尝试):
2 2000
1000 2000x和y多维切片都有2000个元素总计(2000个字节),但是x只存储2切片,每个都有1000元素,而y存储1000切片,每个都存储2元素。
这意味着x需要2片头,而y需要1000片头(对于元素,对于x和y本身是+1 )!
片头由reflect.SliceHeader表示。
type SliceHeader struct {
Data uintptr
Len int
Cap int
}32位架构上的片头大小为12字节,64位结构为24字节。因此,如果x的32位arch元素需要2,000字节加2x12字节,即内存中的2,024字节,而y的元素需要2,000字节加上1,000*12,即14,000字节。
还请注意,多维切片的元素可能包含具有不同长度的片:
对于数组数组,通过构造,内部数组的长度总是相同的;但是,对于切片(或片数组),内部长度可能会动态变化。此外,内部切片必须单独初始化。
如本例所示:
x := make([][]byte, 2)
x[0] = []byte{1, 2}
x[1] = []byte{1, 2, 3, 4}
fmt.Println(x[0])
fmt.Println(x[1])输出(在围棋游乐场上尝试):
[1 2]
[1 2 3 4]如果你还没有读过,推荐:Go博客:数组、切片(和字符串):“追加”的机制
发布于 2021-03-08 06:19:04
对我来说,加入围棋就像vector在C++里一样。Vector还有3个关键的数据成员: ptr到数据、容量和长度。如果vector为2d,子向量的内部长度也会动态变化。
相比之下,Go中的数组看起来就像C中的数组。
https://stackoverflow.com/questions/39561140
复制相似问题