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


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

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

一.数组指针

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]

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

(*arrPtr)[0]
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, 4

arr2 := [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

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

*ptrArr[0]*ptrArr[0]
ptrArr[0]
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]
*ptrArr[0] = 1000ptrArr[0]*a
ptrArr[0]*ptrArr[0] = 1000

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

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

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

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

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