开发者学堂课程【Go语言核心编程 - 基础语法、数组、切片、Map:二维数组使用和内存布局】与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/625/detail/9653
二维数组使用和内存布局(一)
内容介绍:
一、二维数组的使用方式1
二、二维数组的内存布局
三、二维数组的使用方式2
下面介绍二维数组使用方式以及二维数组在内存的存在形式,讲解风格是先分析入门案例,再在案例中讲细节,以及数据结构包括二维数组在内存的存在形式,因为只有理解了数据类型在内存里面的布局,才能深刻的理解这个数组到底是怎么存在的,应用起来就会得心应手。
一、二维数组的使用方式1
方式1:先声明/定义再赋值
1、快速入门案例/使用演示
案例,如:
//定义/声明二维数组
var arr [4][6]int
//赋初值
arr[1][2] = 1
arr[2][1] = 2
arr[2][3] = 3
//遍历二维数组,按照要求输出图形
for i :=0; i<4; i++{
for j:=0; j<6; j++{
fmt.Println(arr[i][j],”")
}
fmt.Println()
}
2、语法: var 数组名[大小[大小]类型
前面的大小是二维数组共有多少个元素,第二个大小指的是二维数组里的各个一维数组有几个元素。
3、比如: var arr [2][3]int[][],再赋值。中括号可以不要。
4、二维数组在内存的存在形式(重点)
二、二维数组的内存布局
下面以 var arr2 [2][3]int 为案例来分析二维数组在内存中的布局
分析
//定义/声明二维数组
var arr [4][6]int
//赋初值
arr[1][2] = 1
arr[2][1] = 2
arr[2][3] = 3
//遍历二维数组,按照要求输出图形
for i :=0; i<4; i++{
for j:=0; j<6; j++{
fmt.Println(arr[i][j],”")
}
fmt.Println()
}
fmt. Print
l
n()
//换行
var arr2 [2][3]int
//以这个为例来分析 arr2在内存的布局! !
arr2[1][1] =10
fmt . Println( arr2) //
输出arr
2
}
此时运行下,运行结果为:
D:
\
goproject\src\go_code\chapter08\nultiarray>go run
main .go
0 0 0 0 0 0
0 0 1 0 0 0
0 2 0 3 0 0
0 0 0 0 0 0
[
[
0 0 0] [0 10 0]]
在 excel 表中分析:
如图左边为代码,右边为在内存中的布局。首先左边第一行代码执行后,会在内存中生成一个名称为 arr2的变量,有一个空间与之对应,但在这个空间里面并没有直接存放 arr2的数据,而是有两个指针,这两个指针都分别指向一个位置,因为可以看到 arr2中是有两个元素,每个元素都指向一个一维数组,所以说这两个指针分别指向了一个一维数组,分析图如下:
下面可以把地址打出来观察下:
首先输出 arr2第一个元素地址,再输出第二个地址,为方便观察要加上\n换行,如下:
…
fmt.Printf("arr2[0]的地址%p\n", &arr2[0])
fmt.Printf("arr2[1]的地址%p\n",&arr2[1])
运行结果:
arr2[0]的地址
0xc
04200
a
270
arr2[1]的地址
0xc
04200
a
288
可以看到出现了两个地址,而两个地址之间相差24个字节,因为每个元素里面有3个 int,而每个i个 int占8个字节,所以两个地址之间相差24个字节,下面打印两个一维数组首地址进行验证:
…
fmt. Printf(”arr2[0][0]的地址%p\n" , &arr2[0][0])
fmt. Printf(”arr2[1][0]的地址%p\n", &arr2[1][0])
运行结果为:
arr2[0]
的地址0xc
04200
a
270
arr2[1]
的地址0xc
04200
a
288
arr2[0][0]
的地址0xc
04200
a
270
arr2[1][0]
的地址0xc
04200
a
288
可以观察到两个一维数组首地址与前面两个指针地址相同,说明刚刚的图示分析没错。
此时把数组改为arr2 [2][2],则说明arr2一个一维数组里面有两个int,就应该相差16个字节,也就是说两个指针地址应该相差16,此时运行结果为:
arr2[0]
的地址0xc
04204
a
0
a
0
arr2[1]
的地址0xc
04204
a
0
b
0
arr2[0][0]
的地址0xc
04204
a
0
a
0
arr2[1][0]
的地址0xc
04204
a
0
b
0
可以发现a0加上16结果是b0。为了更方便观察,改变代码为arr2 [2][1],两个指针就应该相差8个字节:
var arr2 [2][1]int
arr2[1][0] =10
…
运行结果为:
arr2[0]
的地址0xc
042010150
arr2[1]
的地址0xc
042010158
arr2[0][0]
的地址0xc
042010150
arr2[1][0]
的地址0xc
042010158
可以发现50到58确实相差8个字节,那如果改变为arr2 [1][1],则是首先找到arr2里面第二个元素的指针,也就是说找到第二个一维数组空间中下标为1的元素,下标为1就是说第二个元素,这样改动后会发现输出的一维数组值,前面的数组值为0,0,0,后面的数组值为0,10,0,分析图:
代码为:
var arr2 [2][3]int
arr2[1][1]= 10
运行结果:
[
[
0 0 0][0 10 0]]
arr2[0]
的地址0xc
04200a270
arr2[1]
的地址0xc
04200a288
arr2[0][0]
的地址0xc
04200a270
arr2[1][0]
的地址0xc
04200a288
可以看到与分析的相同,第二个一维数组中数值被改为10。