指针
1、指针的使用
一个指针变量指向了一个值的内存地址。
var ip *int /* 指向整型*/
var fp *float32 /* 指向浮点型 */
代码示例
package main
import "fmt"
func main() {
var a int = 20 /* 声明实际变量 */
var ip *int /* 声明指针变量 */
ip = &a /* 指针变量的存储地址 */
fmt.Printf("a 变量的地址是: %x\n", &a)
/* 指针变量的存储地址 */
fmt.Printf("ip 变量储存的指针地址: %x\n", ip)
/* 使用指针访问值 */
fmt.Printf("*ip 变量的值: %d\n", *ip)
}
查看运行结果
2、空指针
当一个指针被定义后没有分配到任何变量时,它的值为
nil
nil 指针也称为空指针 ,一个指针变量通常缩写为ptr
代码示例
package main
import "fmt"
func main() {
var ptr *int
fmt.Printf("ptr: %v\n", ptr)
if ptr == nil {
fmt.Println("ptr是空指针")
} else {
fmt.Println("ptr不是空指针")
}
}
查看运行结果
3、指针数组
- 定义长度为3的整形数组
代码示例
package main
import "fmt"
func main() {
a := []int{10, 20, 30}
for i := 0; i < len(a); i++ {
fmt.Printf("a[%d] = %d\n", i, a[i])
}
}
查看运行结果
- 声明整形指针数组
var ptr [MAX] *int
*** ptr 为整形指针数组,因此每个元素都指向了一个值,下面示例中的三个整数将存储在指针数组中**
代码示例
package main
import "fmt"
func main() {
a := []int{10, 20, 30} //世纪数组
var ptr [3]*int //指针数组申明
//对实际数组进行遍历
for i := 0; i < len(a); i++ {
ptr[i] = &a[i] //整数的地址赋值给指针数组
fmt.Printf("第%d个元素的指针地址%d\n", i, &a[i])
}
//使用指针变量指向值进行遍历
for j := 0; j < len(ptr); j++ {
fmt.Printf("a[%d] = %d\n", j, *ptr[j])
}
}
查看运行结果
4、指向指针的指针
- 概述及实例
-
如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量
-
当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:
-
指向指针的指针变量声明格式如下:
var ptr **int;
代码示例
package main
import "fmt"
func main() {
var (
a int //变量
ptr *int //指针
pptr **int //指向指针的指针
)
a = 100 //变量赋值
//指针ptr地址
ptr = &a
//指向指针ptr地址
pptr = &ptr
//获取pptr的值
fmt.Printf("变量a = %d\n", a)
fmt.Println("变量a的地址 =", &a)
fmt.Printf("指针变量 *ptr = %d\n", *ptr)
fmt.Println("指针pptr指向的值", *pptr)
fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
fmt.Println("pptr指针的地址 =", &pptr)
}
查看运行结果
4、多重指针
pt3——》pto——》ptr——》变量a
代码示例
package main
import "fmt"
func main() {
var (
//变量a
a int = 5
//把ptr指针指向变量a所在地址
ptr *int = &a
//开辟一个新的指针,指向ptr指针所指向的地址
pts *int = ptr
//二级指针,指向一个地址,这个地址存储的是一级指针的地址
pto **int = &ptr
//三级指针,指向一个地址,这个地址存储的是二级指针的地址
pt3 ***int = &pto
)
fmt.Println("a的地址: ", &a)
fmt.Println("a的值: ", a)
fmt.Println("-----------------------------")
fmt.Println("ptr指针所在的地址: ", &ptr)
fmt.Println("ptr指针指向的地址: ", ptr)
fmt.Println("ptr指针指向地址所对应的值: ", *ptr)
fmt.Println("-----------------------------")
fmt.Println("pts指针所在的地址: ", &pts)
fmt.Println("pts指针指向的地址: ", pts)
fmt.Println("pts指针指向地址所对应的值: ", *pts)
fmt.Println("-----------------------------")
fmt.Println("pto指针所在地址: ", &pto)
fmt.Println("pto指针指向的指针(ptr)的存储地址", pto)
fmt.Println("pto指针指向的指针(ptr)所指向的地址: ", *pto)
fmt.Println("pto指针最终指向的地址对应的值: ", **pto)
fmt.Println("------------------------------")
fmt.Println("pt3指针所在的地址: ", &pt3)
fmt.Println("pt3指针指向的指针(pto)的地址", pt3) //等于&*pt3
fmt.Println("pt3指针指向的指针(pto)所指向的指针(ptr)的地址: ", *pt3) //等于&**pt3
fmt.Println("pt3指针指向的指针(pto)所指向的指针(ptr)所指向的地址(a): ", **pt3) //等于&***pt3
fmt.Println("pt3指针最终指向的地址(a)对应的值: ", ***pt3)
}
查看运行结果
5、指针作为函数参数
- 允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可
- 向函数传递指针,并在函数调用后修改函数内的值
代码示例
package main
import "fmt"
func main() {
var (
a int = 100
b int = 300
)
fmt.Printf("交换前a的值: %d\n", a)
fmt.Printf("交换前b的值: %d\n\n", b)
swap(&a, &b)
fmt.Printf("交换后a的值: %d\n", a)
fmt.Printf("交换后b的值: %d\n", b)
}
func swap(x, y *int) {
//值传递,两数交换
*x, *y = *y, *x
}
查看运行结果
总结
取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。
变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:
- 对变量进行取地址(&)操作,可以获得这个变量的指针变量。
- 指针变量的值是指针地址。
- 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。