开发者学堂课程【GO 语言核心编程-基础语法、数组、切片、Map:数组定义和内存布局】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/625/detail/9627
数组定义和内存布局
内容介绍
一、数组的定义
二、数组的内存布局
一、数组的定义
数组的定义
var数组名【数组大小】数据类型 :var 是一个关键字
var a
[
5
]
int
:
a
为数组的名称,5代表数组最多存放5个数据,int 代表此数组能够存放的数据类型是什么
赋初值 a[0]=1a[1]=30… :a[0]代表给第一个元素赋初值,a[1]代表给第二个元素赋初值
二、数组的内存布局
1. 数组内存图(重要)
//使用代码来画图
2. 新建一个文件夹叫 arrarydemo02,新建一个文件叫 main.go
package main
import (
"fmt"
func main() {
//定义一个组函数
//定义一个数组,用于存放 int ,数组大小为可以存放3个数据的数组
var intArr [3]int
//int 占8个字节
//当我们定义完数组后,其实数组的各个元素有默认值0
//打印值
fmt.Println(intArr)
运行结果如下:
三个元素的值都是0。
3.执行完var intArr[3]int
后,内存图中会出现一个 intArr 的变量,会出现一个数组,由于只能存储3个数据,所以空间有3个,空间中每个元素默认为0,intArr 由于是值类型,则会直接指向空间,进行关联,
数组的名字就是数组的首地址
获取地址
f
mt.P
rintf
(“intArr
的地址=
%p”,&intArr)
运行效果如下:
可以看到地址是0
xc04204a0a0
所以可以知道,intArr 是指向地址的首地址0
xc04204a0a0
,而且数组的首地址就是第一个元素的地址
4.测试第一个元素的地址是否跟数组的首地址一样
f
mt.Printf(“intArr
的地址=
%p intArr[0]
地址%
p”,&*intArr,&intArr[0])
保存并运行,出现如下效果:
可以看见,地址完全一致。
5.由此可以推断出第二个元素的地址就是第一个元素地址基础上,加上int数组类型占用的字节数
f
mt.Printf(“intArr
的地址=
%p intArr[0]
地址%
p intArr[1]
地址%
p”,&intArr,&intArr[0]
,int
Arr[1])
运行结果如下:
测试第三个元素的地址
f
mt.Printf(“intArr
的地址=
%p intArr[0]
地址%
p intArr[1]
地址%
p
int
A
rr
[2]
地址%
p”,&intArr,&intArr[0]
,int
Arr[1]
,intArr
[2])
运行结果如下:
可以发现地址都是连在一起的,第一个元素的地址最后一位为0,第二个元素地址最后一位为8,第三个元素的地址最后增加了一个 b0,因为是16进制,需要进位,所以 a 会变成 b,8会变成0。
由此可以得出,数组元素的地址是连续的,这也是 go 语言中的一个特点。
如果想要快速定位一个值,最快的方法就是在地址上加上一个值。例如在第一个元素的地址上加一个8,就可以马上取得下一个元素的地址,然后取值。
6.如果将 var intArr [3]int
改为 var intArr [3]int32
,元素之间的地址还是连续的,而且地址之间每个相差4,因为32是四个字节
运行效果如下:
首地址仍然不变,但是下一个地址增加了一个4,因为 int32每一个元素占了4个字节,所以每个地址需要增加一个4。
所以最终呈现的内存图为:
为什么可以直接把数组的所有元素都取值出来,因为找到首地址之后,每个元素加8个字节,就可以把所有的值都取出来。
进行赋值
intArr[0]= 10 //第一个元素赋值为10
intArr[1]= 20 //第二个元素赋值为20
intArr[2]= 30 //第三个元素赋值为30
保存成功,运行输出结果如下:
通过元素的访问,可以改变各个元素中具体包含的值。
6.内存图:
从图中可以反映出数组是值类型,如果是引用类型的话,intArr 不会直接指向数据空间,而是指向地址。还反映出,内存中的每个元素的地址是连续分布的,而且中间每隔多少是取决于数组的类型。
7.对上图的总结:
(1)数组的地址可以通过数组名来获取&intArr
(2)数组的第一个元素的地址,就是数组的首地址
(3)数组的各个元素的地址间隔是依据数组的类型决定,比如 int64 -> 8 int32->4...
注意:打印地址要是用%p,它代表取出地址