提问人:user3051040 提问时间:12/26/2019 最后编辑:Jonathan Halluser3051040 更新时间:12/26/2019 访问量:127
通过指针修改数据
Modifying data via pointers
问:
https://play.golang.org/p/DOhYaiH53Ek
我不明白这个操作,也不了解一个指针如何能够修改它的即.我知道我一定误解了什么,但这段代码从字面上看似乎是自相矛盾的。*&p
*p
int() value NOT a memory address
value
valueX = valueY
//point
package main
import "reflect"
var pt int = 27
func main() {
println(reflect.TypeOf(pt))
println("pt = ", pt) //value of pt
println("&pt = ", &pt) //memory address of pt
updatePointer(&pt)
println("pt = ", pt) //value of pt
}
func updatePointer(p *int) { //requires memory address of an int
println("&p = ", &p) //memory address of p
println("p = ", p) //memory address of pt
println("*p before = ", *p) //value of pt
println(*p == 27) //true
*p = 14 //27 = 14??????????
println("*p =", *p) //value of pt
println(reflect.TypeOf(&pt) == reflect.TypeOf(*&p)) //true!!!?????
println("*&p = ", *&p) //memory address which p's memory address evals to???? 0x800 (p) -> 0x900 (pt) = 0x800 (p)?
}
/*
Why can't I do the following?
func updatePointer(p *int){
p = 14
//OR
&p = 14
//OR
*&p = 14
}
*/
答:
简化。例如
package main
import "fmt"
func f(q *int) {
fmt.Println(*q, q, &q, "f")
*q = 14
fmt.Println(*q, q, &q, "f")
}
func main() {
var i int = 27
var p *int = &i
fmt.Println(*p, p, &p, i, "main")
f(p)
fmt.Println(*p, p, &p, i, "main")
}
输出:
27 0x40e020 0x40c138 27 main
27 0x40e020 0x40c148 f
14 0x40e020 0x40c148 f
14 0x40e020 0x40c138 14 main
错误:
/*
func g(r *int) {
// cannot use 14 (type int) as type *int in assignment
r = 14
// cannot assign to &r
&r = 14
// cannot use 14 (type int) as type *int in assignment
*(&r) = 14
}
*/
游乐场: https://play.golang.org/p/Hwe3anFBTfD
在 Go 中,所有参数都是按值传递的,就像按赋值传递一样。指向 int 的指针通过值 () 传递给函数 。指针 , 是 的副本,用于修改 , , 的值,取消引用类型为类型。p
i
q = p
f
q
p
i
*q = 14
*q
*int
int
函数编译器错误消息解释了为什么这些语句是非法的。例如,is 是 , 是 类型 。g
*&r = 14
*(&r) = 14
r = 14
cannot use 14 (type int) as type *int in assignment
r
*int
引用:
首先考虑一下,让我们简化示例(删除所有不相关的东西)*&p
var pt int = 27
p := &pt // because &pt is passed as the argument into updatePointer
*p = 14 // This assigns 14 to whatever p points to (i.e. pt)
println(reflect.TypeOf(&pt) == reflect.TypeOf(*&p))
*&
什么都不做(我看不出有什么理由在实际应用程序中使用它);该语句获取 P(位)的地址,然后获取结果指向 () 的内容。所以这是一个被重写的&p
p
println(reflect.TypeOf(&pt) == reflect.TypeOf(p))
p
指向 so(根据定义,这意味着 )。这意味着它们是同一件事,所以当然会具有相同的类型。pt
p == &pt
*p == pt
那么为什么有效呢?你说“*p 是一个 int() 值,而不是一个内存地址,能够修改它的值”,但这并不完全是规范所说的:*p = 14
对于指针类型为 *T 的操作数 x,指针间接 *x 表示 x 指向的 T 类型的变量。如果 x 为 nil,则 尝试计算 *x 将导致运行时崩溃。
所以所说的是将 p 指向的变量设置为 14。*p = 14
现在让我们看看你的第二个问题:
// Why can't I do the following?
func updatePointer(p *int){
p = 14
//OR
&p = 14
//OR
*&p = 14
}
所以 p 是指向整数的指针(这就是这个意思)。Say 是尝试将指针(而不是 int)设置为值 14。14 是 int 而不是指针,因此编译器错误。*int
p = 14
cannot use 14 (type int) as type *int in assignment
&p = 14
就是说把 p 的地址设为 14。 所以获取地址会给你一个(指向指向 int 的指针的指针)。您将得到的编译器错误是,这是因为 的结果不可寻址。你可以通过说p
*int
**int
cannot assign to &p
&p
x := &p
x = 14
这将根据我上面所说的内容为您提供您可能期望的错误:.cannot use 14 (type int) as type **int in assignment
*&p = 14
基本上等同于说(它得到 p 的地址,然后得到 whis 的结果点将是 p)。p=14
指针可能会变得非常混乱(尤其是在人为的例子中),本文可能会帮助您理解。
上一个:带有相等运算符的指针 ( 问题!
下一个:引用相同地址的算术指针
评论