数组定义和内存布局|学习笔记

简介: 快速学习数组定义和内存布局。

开发者学堂课程【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. 数组内存图(重要)

image.png

//使用代码来画图

2. 新建一个文件夹叫 arrarydemo02,新建一个文件叫 main.go

package main

import (

"fmt"

func main() { //定义一个组函数

//定义一个数组,用于存放 int ,数组大小为可以存放3个数据的数组

var intArr [3]int  //int 占8个字节

//当我们定义完数组后,其实数组的各个元素有默认值0

//打印值

fmt.Println(intArr)

运行结果如下:

image.png

三个元素的值都是0。

3.执行完var intArr[3]int 后,内存图中会出现一个 intArr 的变量,会出现一个数组,由于只能存储3个数据,所以空间有3个,空间中每个元素默认为0,intArr 由于是值类型,则会直接指向空间,进行关联,

数组的名字就是数组的首地址

获取地址

fmt.Printf(“intArr的地址=%p”,&intArr)

运行效果如下:

image.png

可以看到地址是0xc04204a0a0

所以可以知道,intArr 是指向地址的首地址0xc04204a0a0,而且数组的首地址就是第一个元素的地址

4.测试第一个元素的地址是否跟数组的首地址一样

fmt.Printf(“intArr的地址=%p intArr[0] 地址%p”,&*intArr,&intArr[0])

保存并运行,出现如下效果:

image.png

可以看见,地址完全一致。

5.由此可以推断出第二个元素的地址就是第一个元素地址基础上,加上int数组类型占用的字节数

fmt.Printf(“intArr的地址=%p intArr[0] 地址%p intArr[1] 地址%p”,&intArr,&intArr[0],intArr[1])

运行结果如下:

image.png

测试第三个元素的地址

fmt.Printf(“intArr的地址=%p intArr[0] 地址%p intArr[1] 地址%p intArr[2] 地址%p”,&intArr,&intArr[0],intArr[1],intArr[2])

运行结果如下:

image.png

可以发现地址都是连在一起的,第一个元素的地址最后一位为0,第二个元素地址最后一位为8,第三个元素的地址最后增加了一个 b0,因为是16进制,需要进位,所以 a 会变成 b,8会变成0

此可以得出,数组元素的地址是连续的,这也是 go 语言中的一个特点。

如果想要快速定位一个值,最快的方法就是在地址上加上一个值例如在第一个元素的地址上加一个8,就可以马上取得下一个元素的地址,然后取值。

6.如果将 var intArr [3]int 改为 var intArr [3]int32,元素之间的地址还是连续的,而且地址之间每个相差4,因为32是四个字节

运行效果如下:

image.png

首地址仍然不变,但是下一个地址增加了一个4,因为 int32每一个元素占了4个字节,所以每个地址需要增加一个4

所以最终呈现的内存图为:
image.png

为什么可以直接把数组的所有元素都取值出来,因为找到首地址之后,每个元素加8个字节,就可以把所有的值都取出来。

进行赋值

intArr[0]= 10  //第一个元素赋值为10

intArr[1]= 20  //第二个元素赋值为20

intArr[2]= 30  //第三个元素赋值为30

保存成功,运行输出结果如下:
image.png

通过元素的访问,可以改变各个元素中具体包含的值。

6.内存图:
image.png

从图中可以反映出数组是值类型,如果是引用类型的话,intArr 不会直接指向数据空间,而是指向地址。还反映出,内存中的每个元素的地址是连续分布的,而且中间每隔多少是取决于数组的类型。

7.对上图的总结:

1)数组的地址可以通过数组名来获取&intArr

2)数组的第一个元素的地址,就是数组的首地址

3)数组的各个元素的地址间隔是依据数组的类型决定,比如 int64 -> 8  int32->4...

注意:打印地址要是用%p,它代表取出地址

相关文章
|
存储 编译器 程序员
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
在C语言中,内存布局是程序运行时非常重要的概念。内存布局直接影响程序的性能、稳定性和安全性。理解C程序的内存布局,有助于编写更高效和可靠的代码。本文将详细介绍C程序的内存布局,包括代码段、数据段、堆、栈等部分,并提供相关的示例和应用。
442 5
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
|
机器学习/深度学习 人工智能 缓存
【AI系统】推理内存布局
本文介绍了CPU和GPU的基础内存知识,NCHWX内存排布格式,以及MNN推理引擎如何通过数据内存重新排布进行内核优化,特别是针对WinoGrad卷积计算的优化方法,通过NC4HW4数据格式重排,有效利用了SIMD指令集特性,减少了cache miss,提高了计算效率。
448 3
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
651 4
|
Rust 安全 Java
内存数组越界
【10月更文挑战第14天】
291 1
|
存储 Java
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
这篇文章详细地介绍了Java对象的创建过程、内存布局、对象头的MarkWord、对象的定位方式以及对象的分配策略,并深入探讨了happens-before原则以确保多线程环境下的正确同步。
225 0
JVM知识体系学习四:排序规范(happens-before原则)、对象创建过程、对象的内存中存储布局、对象的大小、对象头内容、对象如何定位、对象如何分配
|
存储 Java
深入理解java对象的内存布局
这篇文章深入探讨了Java对象在HotSpot虚拟机中的内存布局,包括对象头、实例数据和对齐填充三个部分,以及对象头中包含的运行时数据和类型指针等详细信息。
145 0
深入理解java对象的内存布局
|
存储 安全 Linux
将文件映射到内存,像数组一样访问
将文件映射到内存,像数组一样访问
227 1
|
编译器 Linux API
基于类型化 memoryview 让 Numpy 数组和 C 数组共享内存
基于类型化 memoryview 让 Numpy 数组和 C 数组共享内存
218 0