问 fun1 和 fun2 fun3分别输出什么,为什么?
```go
func fun1() {
a := 2
c := (*string) (unsafe.Pointer(&a))
*c = "44"
fmt.Println(*c)
}
func fun2() {
a := "654"
c := (*string) (unsafe.Pointer(&a))
*c = "44"
fmt.Println(*c)
}
func fun3() {
a := 3
c := *(*string) (unsafe.Pointer(&a))
c = "445"
fmt.Println(c)
}
```
如果知道c语言的void*指针和string的内存布局,这个问题其实不难,强烈建议看看这门课: `http://open.163.com/special/opencourse/paradigms.html`.
unsafe.Pointer相当于void*,也就是无类型指针,可以指向任何地址的指针。
在go中,string的内存布局如下:
```
+---------+ -----------------------
| data | ------> | string的真实内容|
+---------+ -----------------------
| len |
+---------+
```
注意:`这里的的data就是一个指向string内容的指针,len是string的长度,在64位的系统中sizeof(data)==8, sizeof(len)==8, 一共占用16byte`。
这里只解释fun1,其他函数自己按照理解去体会(以下解释默认在64位系统中)
```
a := 2 // 申请一个int类型,占用8byte,其内容为2.
c := (*string) (unsafe.Pointer(&a)) // c为*string类型,占用8byte,指向a的指针,a的内容为2
*c = "44" // 将 string==“44”赋值给c,注意我前面讲过一个string占用16byte,而原来的c,也就是a只申请了8byte,超过了你程序申请的字节数,当访问*c的时候,一般情况下你会panic,类似数组越界。
fmt.Println(*c)
```
#50
更多评论
```go
func fun1() {
a := 2
c := (*string) (unsafe.Pointer(&a)) //c为a的unsafe.pointer强制转为string指针,*c指的是a的值,a的值是int型的,这里*c = "44"是强制赋了个字符串,所以赋值是失败的,只是没有提示,因为使用了unsafe
*c = "44"
fmt.Println(*c) //这时的c是string指针,*c指的应该是一个字符串,但是里面实际上是int数据,所以操作也是失败的
}
func fun2() {
a := "654"
c := (*string) (unsafe.Pointer(&a)) //根据fun1的解释 a 为字符串型,那整个流程就通了,自然*c打出来的是 44,在*c="44"上面打印出来的是肯定是654
*c = "44"
fmt.Println(*c)
}
func fun3() {
a := 3
c := *(*string) (unsafe.Pointer(&a)) //这里获取的是a地址里的string值,但a的值是int型,所以操作失败,没有得到值,但c被定义里了string型变量,c = "445",给string型变量赋string值 自然是正常的
c = "445"
fmt.Println(c)
}
```
#1