跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • golang 的指针地址问题
未分類
14 1 月 2021

golang 的指针地址问题

golang 的指针地址问题

資深大佬 : yellowmarlboro 2

 s0 := "something"  s1 := "something"  s2 := "something"[7:]  fmt.Println(&s0, &s1, &s2)  fmt.Printf("%d n", (*reflect.StringHeader)(unsafe.Pointer(&s0)).Data)  fmt.Printf("%d n", (*reflect.StringHeader)(unsafe.Pointer(&s1)).Data)  fmt.Printf("%d n", (*reflect.StringHeader)(unsafe.Pointer(&s2)).Data) 

结果是

0xc00010a040 0xc00010a050 0xc00010a060 4974445  4974445  4974452 
  • 为什么 & 出来的总差 16 ? unsafe.Pointer 是一样的?(请忽略切片的)
大佬有話說 (11)

  • 主 資深大佬 : yellowmarlboro

    已经了解!
    End

  • 資深大佬 : iQXQZX

    为什么为什么为什么?插眼

  • 資深大佬 : iamzuoxinyu

    分清栈上变量和字符串常量。

  • 資深大佬 : koujyungenn

    @yellowmarlboro 谜语人?

  • 資深大佬 : kakach

    蹲一个大佬的回答

  • 資深大佬 : kiddingU

    你自己用法姿势不对,正确的应该是这样吧:unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s0)))

  • 資深大佬 : yuguorui96

    没翻源码,花了几分钟看了下汇编。

    s0, s1, s2 之间的地址总差 16 是因为 String 在栈上的结构是:
    struct String {
    char *data;
    int length;
    };
    sizeof(一个指针)+sizeof(一个 int)正好是 16 字节( 64 位环境下)。

    又因为栈上变量都是编译器按序分配的,所以有了主看到的结果。

    至于为啥 unsafe.Pointer 显示的结果是一致的,我个人猜测是因为字符串常量池(这个得去翻 Golang 的编译器,一会儿早上有会就不深挖了),即相同的字符串不会在内存中存在两次,有多次引用就把上面 data 的指针指向实际存储数据的 backing store 。这是一个常见优化,Python 中也存在。

  • 資深大佬 : Dganzh

    字符串实际是一个**stuct
    struct string {
    byte* str;
    intgo len;
    }

    大小就是 16
    unsafe.Sizeof(s0) == 16

  • 資深大佬 : kiddingU

    import (
    “github.com/davecgh/go-spew/spew”
    “reflect”
    “unsafe”
    )

    func main() {
    s0 := “something”
    s1 := “something”
    spew.Dump(&s0)
    spew.Dump(&s1)
    spew.Dump((*reflect.StringHeader)(unsafe.Pointer(&s0)))
    spew.Dump((*reflect.StringHeader)(unsafe.Pointer(&s1)))
    }

    ————–
    (*string)(0xc0001042b0)((len=9) “something”)
    (*string)(0xc0001042c0)((len=9) “something”)
    (*reflect.StringHeader)(0xc0001042b0)({
    Data: (uintptr) 0x1101229,
    Len: (int) 9
    })
    (*reflect.StringHeader)(0xc0001042c0)({
    Data: (uintptr) 0x1101229,
    Len: (int) 9
    })

  • 資深大佬 : kiddingU

    @yuguorui96 编译一下,可以看到,golang 对于相同的字符串确实是做了优化处理,只存一份的

  • 資深大佬 : iQXQZX

    @kiddingU 学到了

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具