Golang中数组指针的问题解析

Golang中数组指针的问题解析 我认为指针是变量的内存地址(十六进制值),当我打印数组的指针时,输出是 &[1, 2, 3] 而不是我预期的结果。我遗漏了什么?

package main

import "fmt"

func main(){
	var a = [3]int{1, 2, 3}
	var p = &a
	fmt.Println(a)
	fmt.Println(&a)
	fmt.Println(p)
	fmt.Println(*p)
}

以下是输出:

[1 2 3]
&[1 2 3]
&[1 2 3]
[1 2 3]

当我尝试 fmt.Println(*p[1]) 时出现错误 invalid indirect of p[1] (type int)。如果我改为 fmt.Println((*p)[1]) 就能正常工作。那么 *p[1] 有什么问题呢?

谢谢


更多关于Golang中数组指针的问题解析的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

我发现了类似的问题 https://github.com/golang/tour/issues/226 请查看。我认为这是同样的问题,如果你找到更好的解决方案请告诉我 🙂

更多关于Golang中数组指针的问题解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你想打印地址吗?那么你需要使用 fmt.Printf()%p 作为指针的格式说明符。

func main() {
    fmt.Println("hello world")
}

*p[1] 被解析为位置1的指针数组,而你想要的是指向数组的指针。 Go 将这个表达式解析为 *(p[1]),因此你需要写成 (*p)[1]。 Go 提供了一个快捷方式,所以你只需要写 p[1]… 🙂

在Go语言中,数组指针的行为确实需要特别注意。你的观察是正确的,这里涉及到Go语言中指针解引用和运算符优先级的规则。

首先,当你打印数组指针时,fmt.Println(&a)fmt.Println(p) 都输出 &[1 2 3],这是Go语言fmt包对数组指针的格式化输出方式,显示这是一个指向数组的指针。

关于 *p[1] 的问题,关键在于Go语言的运算符优先级。[] 索引操作符的优先级高于 * 解引用操作符。

示例代码演示:

package main

import "fmt"

func main() {
    var a = [3]int{1, 2, 3}
    var p = &a
    
    // 错误的方式:*p[1]
    // 这会被解析为 *(p[1]),但p是指向数组的指针,不是slice
    // fmt.Println(*p[1]) // 编译错误:invalid indirect of p[1] (type int)
    
    // 正确的方式:(*p)[1]
    // 先用括号解引用指针得到数组,然后访问索引
    fmt.Println((*p)[1]) // 输出: 2
    
    // 另一种语法糖:p[1]
    // Go语言允许直接通过数组指针访问元素
    fmt.Println(p[1])    // 输出: 2
    
    // 验证所有访问方式的结果相同
    fmt.Printf("a[1] = %d\n", a[1])
    fmt.Printf("(*p)[1] = %d\n", (*p)[1])
    fmt.Printf("p[1] = %d\n", p[1])
}

运算符优先级解析:

  • *p[1] 被解析为 *(p[1]):先尝试访问 p[1],然后对结果解引用
  • (*p)[1] 被解析为:先解引用 p 得到数组,然后访问索引 [1]

Go语言为数组指针提供的语法糖:

Go语言允许直接通过数组指针访问元素,无需显式解引用:

var a = [3]int{1, 2, 3}
var p = &a

// 以下三种方式等价
fmt.Println(a[1])     // 直接访问数组
fmt.Println((*p)[1])  // 显式解引用后访问
fmt.Println(p[1])     // 通过指针直接访问(语法糖)

这种设计使得通过指针操作数组更加方便,避免了频繁使用括号进行显式解引用。

回到顶部