二维数组的内存表示是什么

二维数组的内存表示是什么

本文介绍了二维数组的内存表示是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中,二维数组是多维一维数组.这意味着那些一维数组在内存中不连续.

In Java, two dimensional array is multi one-dimensional array. That means those one-dimensional arrays not consecutive on memory.

相反,在C语言中,二维数组实际上是尺寸为 total_row * total_column 的一维数组.因为Go语言使用了C语言中的许多概念.

In contrast, in C, two dimensional array in fact is one-dimensional array with size is total_row * total_column. Because Go language uses many concepts from C.

所以我的问题是:Go中的二维数组的内存表示看起来像C还是Java?

So my question is: does two dimensional array's memory representation in Go look like C or Java?

推荐答案

在Go中,切片经常被误认为数组,所以我对两者都回答.

In Go, slices are often mistaken for arrays, so I answer regarding both.

引用规范:数组类型:

您的答案清晰明了.但是答案不只是因为数组是Go中的值,它们也不像切片一样是描述符(标头).

There you have your answer plain and clear. But the answer is not just that as arrays are values in Go, they are not descriptors (headers) like slices.

看这个简单的例子:

x := [5][5]byte{}
fmt.Println(&x[0][3])
fmt.Println(&x[0][4])
fmt.Println(&x[1][0])

输出(在进入游乐场上尝试):

0x10432203
0x10432204
0x10432205

如您所见,为数组分配和使用的内存是连续的:第二行从内存地址开始,该地址是第一行最后一个元素的地址的后继地址.

As you can see, the memory allocated and used for the array is contiguous: the second row starts at a memory address that is the subsequent to the address of the last element of the first row.

检查数组大小:

fmt.Println(unsafe.Sizeof([4][6]int{})) // 96
fmt.Println(unsafe.Sizeof([6][4]int{})) // 96

切换行和列无关紧要,它的大小是相同的.

It doesn't matter if you switch rows and columns, its size is the same.

在切片的情况下也是如此:多维切片是切片的切片. 规范:切片类型:

The same applies in case of slices: a multidimensional slice is a slice of slices. Spec: Slice types:

切片是描述符,切片头包含指向基础(支持)数组的元素的指针,长度和容量.因此,总片数取决于内存使用情况.

Slices are descriptors, a slice header contains a pointer to an element of an underlying (backing) array, a length and a capacity. So the number of total slices matters in terms of memory usage.

请参见以下示例:

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 2000

xy多维切片总共有2000个元素(2000个字节),但是x仅存储2个切片,每个切片都有1000个元素,而y存储1000个切片,每个元素都有2个元素.

Both x and y multidimensional slices have 2000 elements total (2000 bytes), but x stores 2 slices only, each having 1000 elements, while y stores 1000 slices, each having 2 elements.

这意味着x需要2条带头,而y需要1000条带头(对于元素,xy本身为+1)!

This means x requires 2 slice headers while y requires 1000 slice headers (for the elements, +1 for x and y themselves)!

切片标头由 reflect.SliceHeader :

A slice header is represented by 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字节.

The size of a slice header on 32-bit architectures is 12 bytes, on 64 bit architectures its 24 bytes. So in case of 32-bit arch elements of x require 2,000 bytes plus 2x12 bytes in memory which is 2,024 bytes, while elements of y require 2,000 bytes plus 1,000*12 which is 14,000 bytes.

还要注意,多维切片的元素可能包含具有不同长度的切片:

Also note that elements of a multidimensional slice may contain slices with different lengths:

如本例所示:

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]


如果您还没有读过,建议您: The Go博客:数组,切片(和字符串): '追加'

这篇关于二维数组的内存表示是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 10:35