Golang中数组指针和指针数组区别

  • 一.数组指针
    • 1.语法
    • 2.实例
    • 3.通过指针访问数组
  • 二.指针数组
    • 1.语法
    • 2.实例

区别二者,字面上只看 后两个字即可:
数组指针 :它是一个指针,但是数据类型为数组,或者说指向数组

指针数组 :它是一个数组,该数组的元素都为地址值

一.数组指针

1.语法

var 变量名 *[数组大小] 数组类型:

var arrPtr *[size] Type

因为数组指针是一个指针,所以在定义时,先写 *, 表示定义一个指针,后面接数据类型

2.实例

一步一步创建,容易理解。
创建一个数组指针,并赋值:


var arrPtr * [4]int        // 创建一个指针 arrPtr,指向一个数组
var arr = [4]int{1,2,3,4}  // 创建一个数组并初始化
arrPtr = &arr              // 将数组 arr的地址赋值给arrPtr
fmt.Println("将 arr 的内存地址赋值给数组指针 arrPtr,   arrPtr=",ptr)

输出为:

将 arr 的内存地址赋值给数组指针 arrPtr,   arrPtr= &[1 2 3 4]

注意,输出的结果不是地址(不是16进制的数),在Golang中,直接输出的是

&[元素1 元素2 …]

我们可以输出一下二者的地址:

fmt.Printf("arr 数组的地址为:%p\n", &arr)
fmt.Printf("arrPtr 存储的地址为:%p\n", arrPtr)

输出为:

arr 数组的地址为:0xc00000c3c0
arrPtr 存储的地址为:0xc00000c3c0

可以看到,它俩的输出时一样的,因为将数组 arr的地址赋值给了arrPtr,而arrPtr是一个指针,存储的是内存地址。

当然arrPtr也有自己的内存地址,我们可以看一下:

fmt.Printf("arrPtr 指针自己的地址为:%p\n", &arrPtr)

输出为:

arrPtr 指针自己的地址为:0xc000006028

3.通过指针访问数组

访问数组的元素可以通过下标来访问,比如:arr[0] 即可访问数组arr的第一个元素。

但是我们学习了指针数组,所以尝试使用指针数组来访问元素内容,在Golang中,取地址的操作为 * (寻址运算符) 。

因此,我们先取存储的地址*arrPtr,访问到数组 ,然后再下标取值*arrPt[0],代码如下:

*arrPtr[0]

实际上,这段代码编译就会报错,因为在Golang 中 * 寻址运算符和 [] 中括号运算符的优先级是不同的!

  • [] 中括号是初等运算符
  • 寻址运算符是单目运算符

初等运算符的优先级是大于单目运算符的,因此先参与计算的是 arrPtr[0]arrPtr[0] 其实就是数组的第一个元素,就是数字1。
数字1必然是int类型,而不是一个地址,因此针对数字1使用*寻址运算符自然也就发生了错误。

解决问题的办法很简单,就是添加一个小括号,更改运算优先级即可:

(*arrPtr)[0]

不过因为 * 在Golang中,建立了 arrPtr := &arr 这种类似地址关系后,* 允许不写。

所以,访问时候可以直接写成arrPtr[0]。事实上在工作开发过程中,这种写法反而更加常见。实战代码:

fmt.Println("(*arrPtr)[0] 通过指针访问数组的第一个元素:", (*arrPtr)[0])
fmt.Println("arrPtr[0] 通过指针访问数组的第一个元素:", arrPtr[0])

输出:

(*arrPtr)[0] 通过指针访问数组的第一个元素: 1
arrPtr[0] 通过指针访问数组的第一个元素: 1

注意:仅对访问下标时,寻址运算符允许不写!

二.指针数组

它是一个数组,该数组的元素都为地址值

1.语法

var 变量名 [数组大小] * 数组类型:

var ptrArr [size] *Type

因为指针数组是一个数组,所以在定义时,先写 [size], 表示定义一个数组,后面再接指针 * 和 数组的数据类型

2.实例

1.创建一个数组指针, 数组的类型为int,大小为4,并赋值:

var ptrArr [4]*int
a, b, c, d := 1, 2, 3, 4arr2 := [4]int{a, b, c, d}  // 拷贝四个变量的值为函数组元素
fmt.Println("数组 arr2 :", arr2)ptrArr = [4]*int{&a, &b, &c, &d} // 存的都是内存地址
fmt.Println("指针数组 ptrArr :", ptrArr)

输出:

数组 arr2 : [1 2 3 4]
指针数组 ptrArr : [0xc0000140f0 0xc0000140f8 0xc000014100 0xc000014108]

2.操作数据,查看变化

(1).arr2的第一个元素改变, a 会不会变化,ptrArr 会不会变化?

arr2[0] = 100
fmt.Println("arr2 的值为:", arr2)
fmt.Println("a 的值为;", a)
fmt.Println("ptrArr 的值为;", *ptrArr[0])

输出:

arr2 的值为: [100 2 3 4]
a 的值为; 1
ptrArr 的值为; 1

先看a 的值为 1解释:
在Golang中,int,float,bool,string,array,struct都属于值类型,数据拷贝时都是值拷贝,拷贝副本过来。

因此,尽管 arr2[0] = 100执行了,只是修改了 arr2 的值,原来 a 的值不会受任何影响。因此,a 的值仍为1

ptrArr的值为1解释:
ptrArr是指针数组, 该数组存储都是 指针,也就是 a,b,c,d四个变量的内存地址。

其中,*ptrArr[0]存储的是 a 的内存地址;a 没变, *ptrArr[0]也不会变。所以输出仍为1

我们可以查看一下 ptrArr[0]的值和 a 的地址是否一致:

fmt.Println("ptrArr[0] 的值:", ptrArr[0])
fmt.Printf("a 的内存地址为:%p\n", &a)  // %p 占位符表示地址值

输出:

ptrArr[0] 的值: 0xc0000140f0
a 的内存地址为:0xc0000140f0

可以看到,它俩的值是一致的。

(2).指针数组变化,a,b,c,d 会不会改变? 数组 arr2 会不会改变?

*ptrArr[0] = 1000  // 指针数组的第一个元素地址指向的值发生改变
fmt.Println("a 的值为:", a)
fmt.Println("arr2 的值为:", arr2)

输出:

a 的值为: 1000
arr2 的值为: [100 2 3 4]

a 的值为: 1000 解析:
首先要明白一点:*ptrArr[0] = 1000 这段代码不会编译报错,因为ptrArr是指针数组,按照运算符的执行顺序,先 ptrArr[0] 获取 a 的地址,然后再 *a,这样获取的就是 a 的值

其实,解析的已经差不多了,ptrArr[0] 本来就是 a 的内存地址,所以*ptrArr[0] = 1000 执行后,就改变了 a 的值

arr2 的值为: [100 2 3 4] 解析:

arr2 拷贝了 a,b,c,d 值的副本,a的改变和 arr2 没有关系的,各不会受影响。a 和 arr2 都是值类型,各自改变,互不影响

以上就是在学习Golang数组指针和指针数组时的一些笔记和感悟。

总结一下,数组指针和指针数组这两个概念的区分,记住两点即可:

  • 后两字是啥,则它就表示啥
  • 定义时,最先写的 代码 就已经表示了其是数组还是指针

Golang学习——数组指针和指针数组的区别相关推荐

  1. 【C语言进阶深度学习记录】三十一 数组作为函数参数时退化为指针

    之前的学习数组的文章中,已经知道一维数组作为函数参数的时候,最终会被编译器编译为指针.今天来看看二维数组的情形 文章目录 1 为什么C语言中的数组作为函数参数会退化为指针? 2 二维数组作为函数参数如 ...

  2. 【C语言进阶深度学习记录】二十八 数组指针与指针数组的分析

    数组指针与指针数是非常重要的概念.面试中也是经常会被问到的 文章目录 1 数组的类型 1.1 定义数组的类型 2 数组指针 2.1 数组类型和数组指针的代码分析 3 指针数组 3.1 指针数组代码案例 ...

  3. 一维数组所有元素是否大于_【C语言】- 指向一维数组元素的指针!你今天学习了吗?...

    前面我们已经学习了指针,如果指针存储了某个变量的地址,我们就可以说指针指向这个变量.数组及其数组元素都占有存储空间,都有自己的地址,因此指针变量可以指向整个数组,也可以指向数组元素. 一.用指针指向一 ...

  4. 数组存储与指针学习笔记(三)指针与数组

    嵌入式C语言学习进阶系列文章 GUN C编译器拓展语法学习笔记(一)GNU C特殊语法部分详解 GUN C编译器拓展语法学习笔记(二)属性声明 GUN C编译器拓展语法学习笔记(三)内联函数.内建函数 ...

  5. Go 学习笔记(13)— 指针定义、指针特点、空指针、指针数组、指向指针的指针、指针作为函数入参

    1. 复合数据类型 Go 语言基本的复合数据类型有指针.数组.切片.字典.通道.结构和接口等.格式如下: * pointerType // 指针类型, [n]elementType // 数组类型, ...

  6. C语言学习笔记--预编译/宏定义/数组/参数传递/函数指针

    目录 预编译 值传递.指针传递.引用传递 数组 typedef 函数指针 预编译 预编译又叫预处理.预编译不是编译,而是编译前的处理.这个操作是在正式编译之前由系统自动完成的.#define 和 #i ...

  7. (C/C++学习)6.数组指针和指针数组

    说明:int (*p)[4] 和 int *p[4](数组指针和指针数组),如果你是一个初学者,也许当你看到这两个名词的时候,已经懵了.其实,只要你理解了其中的含义.这两个名词对你来说会相当简单并且很 ...

  8. c语言数组宏定义标识符,C语言学习笔记--预编译/宏定义/数组/参数传递/函数指针...

    目录 预编译 值传递.指针传递.引用传递 数组 typedef 函数指针 预编译 预编译又叫预处理.预编译不是编译,而是编译前的处理.这个操作是在正式编译之前由系统自动完成的.#define 和 #i ...

  9. Golang——指针的使用、数组指针和指针数组、指针与切片、指针与结构体、多级指针

    指针: 指针是一个特殊的变量,因为存储的数据不仅仅是一个普通的数据,而是一个变量的内存地址,指针本身也是有内存地址的 指针的数据类型有int.float.bool.string.数组.结构体 指针的作 ...

最新文章

  1. 7-31 字符串循环左移 (C语言)
  2. Runtime.getRuntime()
  3. Windows PE第九章 线程局部存储
  4. joomla建站-双语CMS系统开发的实现
  5. Java Web应用程序:Oozie及其使用方式
  6. 用eclipse创建动态web项目手动生成web.xml方法
  7. C#的变迁史04 - C# 4.0 之多线程篇
  8. 数据结构开发(3):线性表的顺序存储结构
  9. java 验证码 添加背景图_java登陆界面怎么加背景图 会的我加你
  10. I.MX6 隐藏电池图标
  11. javaweb(05):tomcat服务器的安装、启动,IDEA整合Tomcat创建动态web工程
  12. html商城加减号,商城购物车的加减号控制商品数量
  13. MFC把 ListCtrl的数据导出到excel表格
  14. php bouncy castle,基础才是重中之重~BouncyCastle实现的DES3加密~java通用
  15. Redis详情教学加源码,欢迎大家来下载
  16. c语言成绩管理程序设计,成绩管理程序设计报告(含代码C语言
  17. 重磅!《中国医学影像人工智能发展报告2021-2022》
  18. 欧洲急了,正式发起 2nm 芯片总攻
  19. 民法学习入门的“听说读写”之道
  20. matlab 光平面标定代码,线结构光视觉传感器/线激光深度传感器标定工具(matlab)...

热门文章

  1. UI设计中的按钮设计规范
  2. H5脱单盲盒交友解密授权版/分销提现/存取小纸条盲盒匹配管理平台/免签支付/可封装APP/带教程-亲测可用
  3. 国仁网络资讯:抖音小店开通流程与保证金缴纳;小店禁品类目抖音哪些?
  4. UINavigationController使用详解
  5. 《简易二手车交易系统案例—控制台—JAVA—IDEA》
  6. office2019 for Mac(Office 2019 for Mac 16.26 VL)
  7. 暗影精灵8pro下载ubuntu双系统18.04遇到的问题
  8. 计算机主要学的是什么意思是,电脑超频是什么意思 超频对电脑的用处
  9. php动图加水印,php+imagemagick给gif动态图片添加水印
  10. HUSTOJ 流程图