当前位置: 首页 > 面试题库 >

二维数组的内存表示如何

韩景辉
2023-03-14
问题内容

众所周知,在Java中,二维数组是多维一维数组。这意味着那些一维数组在内存中不连续。

相反,在C中,二维数组实际上是大小为 total_row * total_column的
一维数组。因为Go语言使用了C语言中的许多概念。所以我的问题是:Go语言中的二维数组的内存表示是否像C或Java中那样?


问题答案:

在Go中,通常将slice误认为是array,所以我对两者都作了回答。

数组

引用规范:数组类型:

数组类型始终是一维的, 但可以组成多维类型。

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

看这个简单的例子:

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

输出(在Go Playground上尝试):

0x10432203
0x10432204
0x10432205

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

检查数组大小:

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

切换行和列无关紧要,其大小相同。

切片

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

切片是 基础数组 连续段的描述符,并提供对该数组中元素编号序列的访问。

像数组一样,切片始终是一维的,但可以组成更高维度的对象。

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

请参阅以下html" target="_blank">示例:

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]))

输出(在Go Playground上尝试):

2 2000
1000 2000

xy多维片具有2000个元素总(2000个字节),但x存储2仅切片,每个具有1000元件,而y存储1000切片,每个具有2元件。

这意味着x需要2片头,同时y需要1000切片头(用于元素+1 xy自己)!

切片标头表示为reflect.SliceHeader

type SliceHeader struct {
    Data uintptr
    Len  int
    Cap  int
}

在32位架构上,切片标头的大小为12个字节,在64位架构上,其为24个字节。因此,对于32位arch元素,x要求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])

输出(在Go Playground上尝试):

[1 2]
[1 2 3 4]

如果您还没有读过,推荐您:The Go Blog:数组,切片(和字符串):“
append”的机制



 类似资料:
  • 问题内容: 据我了解,我可以将混合数据存储在JavaScript数组中,也可以将数组中的任何元素更改为其他类型。解释器如何跟踪任何元素在物理内存中的位置。另外,如果将元素更改为更大的数据类型,那么如何防止下一个元素中的数据被覆盖。 我假设数组仅存储对实际对象的引用,并且将基元放置在数组中时将其包装在幕后。 假设是这种情况,如果我对原始变量有不同的句柄并更改存储在数组中的值是否保持同步? 我知道我可

  • 我正在编写一个计算和绘制抛物线的小程序。但我在程序中有一小部分需要计算valuetable。 二次函数如下:

  • 二维数组 #include <stdio.h> #include <stdlib.h> //01.二维数组: // 1.二维数组的内存存储原理: // 所有数组,无论一维数组,二维数组,多维数组,在内存当中的 // 存储实质都是采取的连续存储方式 // 2.二维数组的规律赋值方式: // 先进行行遍历,在进行列遍历,再逐个进行逐个数组元素的具体赋值操作 //

  • 问题内容: 我已经有了用于将一维二维转换为一维二维的代码,但是我不知道如何将其转换。这是我的代码: 问题答案: 您正在寻找类似的东西: 与以下内容相同: 但试图帮助进一步解释这个概念。

  • 我有以下代码: 但当我试着去看测试的内容时,我看到了这个 如果我试图看到什么是在任何项目的数组我得到一个错误: 有人能解释一下我做错了什么,正确的方法是什么吗? Visual Studio 2022, Blazor Webassup,.NET6.0 谢谢

  • 主要内容:指针数组和二维数组指针的区别二维数组在概念上是二维的,有行和列,但在内存中所有的数组元素都是连续排列的,它们之间没有“缝隙”。以下面的二维数组 a 为例: int a[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; 从概念上理解,a 的分布像一个矩阵: 但在内存中,a 的分布是一维线性的,整个数组占用一块连续的内存: C语言中的二维数组是按行排列的,也就是先存放