Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Apakah operasi pada penunjuk dalam bahasa go?

Apakah operasi pada penunjuk dalam bahasa go?

青灯夜游
青灯夜游asal
2023-01-04 10:30:293486semak imbas

Bahasa Go tidak mempunyai aritmetik penunjuk. Sintaks bahasa go tidak menyokong aritmetik penunjuk, dan semua penunjuk digunakan dalam julat yang boleh dikawal tetapi sebenarnya, bahasa go boleh menggunakan kaedah Pointer() pakej tidak selamat untuk menukar penunjuk kepada nombor jenis uintptr untuk Melaksanakan secara tidak langsung; aritmetik penunjuk.

Apakah operasi pada penunjuk dalam bahasa go?

Persekitaran pengendalian tutorial ini: sistem Windows 7, GO versi 1.18, komputer Dell G3.

Apakah sebenarnya penunjuk?

Memori ialah satu siri unit storan dengan nombor siri Pembolehubah ialah nama panggilan yang diberikan oleh pengkompil kepada alamat memori.

Penunjuk ialah nilai yang menunjuk kepada pembolehubah alamat memori yang lain

Penunjuk menunjuk ke alamat memori pembolehubah, dan penuding adalah seperti alamat memori bagi nilai pembolehubah

Mari kita lihat coretan kod

func main() {
    a := 200
    b := &a
    *b++
    fmt.Println(a)
}

Dalam baris pertama fungsi utama, kami mentakrifkan pembolehubah baharu a dan memberikannya nilai 200. Seterusnya kita mentakrifkan pembolehubah b dan menetapkan alamat pembolehubah a kepada b. Kami tidak tahu alamat storan yang tepat bagi a, tetapi kami masih boleh menyimpan alamat a dalam pembolehubah b.

Apakah operasi pada penunjuk dalam bahasa go?

Apakah operasi pada penunjuk dalam bahasa go?

Disebabkan sifat Go yang ditaip kuat, baris ketiga kod mungkin yang paling mengganggu, b mengandungi a Alamat pembolehubah, tetapi kami ingin menambah nilai yang disimpan dalam pembolehubah.

Dengan cara ini kita perlu membatalkan rujukan b dan sebaliknya merujuk kepada a dengan b mengikut penunjuk.
Kemudian kami menambah 1 pada nilai dan menyimpannya semula pada alamat memori yang disimpan dalam b.

Barisan terakhir mencetak nilai a Anda dapat melihat bahawa nilai a telah meningkat kepada 201

Apakah operasi pada penunjuk dalam bahasa go?

Apakah operasi pada penunjuk dalam bahasa go?

Parameter fungsi dalam bahasa Go adalah semua salinan nilai Apabila kita ingin mengubah suai pembolehubah, kita boleh mencipta alamat yang menunjuk kepada pembolehubah. . Pembolehubah penunjuk .

Berbeza daripada penunjuk dalam C/C++, penunjuk dalam bahasa Go tidak boleh diimbangi dan dikendalikan, dan merupakan penunjuk selamat.

Untuk memahami penunjuk dalam bahasa Go, anda perlu mengetahui tiga konsep: Alamat penunjuk, jenis penunjuk dan nilai penunjuk.

Alamat penuding dan jenis penuding

Operasi penunjuk dalam bahasa Go adalah sangat mudah, anda hanya perlu mengingati dua simbol: & (ambil alamat ) dan * (nilai berdasarkan alamat).

Setiap pembolehubah mempunyai alamat pada masa jalan, yang mewakili lokasi pembolehubah dalam ingatan. Dalam bahasa Go, aksara & digunakan di hadapan pembolehubah untuk "mendapatkan alamat" pembolehubah.

Sintaks untuk mengambil penuding pembolehubah adalah seperti berikut:

ptr := &v    // v的类型为T

di mana:

  • v: pembolehubah yang mewakili alamat untuk diambil, jenisnya ialah T

  • ptr: pembolehubah yang digunakan untuk menerima alamat Jenis ptr ialah *T, yang dipanggil jenis penunjuk T. * bermaksud penunjuk.

Apakah operasi pada penunjuk dalam bahasa go?

func main() {
    a := 10
    b := &a
    fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
    fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
    fmt.Println(&b)                    // 0xc00000e018
}

Operator Penunjuk

1 rnilai, kita boleh mengemas kini keadaan objek sasaran apabila ia adalah nilai, ia adalah untuk mendapatkan keadaan sasaran.

func main() {
    x := 10
    var p *int = &x  //获取地址,保存到指针变量
    *p += 20        //用指针间接引用,并更新对象
    println(p, *p)  //输出指针所存储的地址,以及目标对象
}

Output:

0xc000040780 30

2 Jenis penunjuk menyokong pengendali kesamaan, tetapi tidak boleh melakukan penambahan, penolakan dan penukaran jenis. Dua penunjuk adalah sama jika ia menunjuk ke alamat yang sama atau kedua-duanya tiada.

func main() {
    x := 10
    p := &x

    p++   //编译报错 invalid operation: p++ (non-numeric type *int)
    var p2 *int = p+1  //invalid operation: p + 1 (mismatched types *int and int)
    p2 = &x
    println(p == p2)   //指向同一地址
}

Anda boleh menggunakan tidak selamat.Penunjuk untuk menukar penuding kepada uintptr dan kemudian melakukan operasi tambah dan tolak, tetapi ia boleh menyebabkan capaian yang menyalahi undang-undang.

Aritmetik penunjuk

Dalam banyak program golang, walaupun penunjuk digunakan, ia tidak menambah atau menolak penunjuk Ini berbeza daripada program C . Alat pembelajaran pengenalan rasmi Golang (go tour) malah mengatakan bahawa Go tidak menyokong aritmetik penunjuk. Walaupun ini sebenarnya tidak berlaku, nampaknya saya tidak pernah melihat aritmetik penunjuk dalam program go biasa (baik, saya tahu anda mahu menulis program yang luar biasa).

  • 但实际上,go 可以通过 unsafe.Pointer 来把指针转换为 uintptr 类型的数字,来间接实现指针运算。
  • 这里请注意,uintptr 是一种整数类型,而不是指针类型。

比如:

uintptr(unsafe.Pointer(&p)) + 1

就得到了 &p 的下一个字节的位置。然而,根据 《Go Programming Language》 的提示,我们最好直接把这个计算得到的内存地址转换为指针类型:

unsafe.Pointer(uintptr(unsafe.Pointer(&p) + 1))

因为 go 中是有垃圾回收机制的,如果某种 GC 挪动了目标值的内存地址,以整型来存储的指针数值,就成了无效的值。

同时也要注意,go 中对指针的 + 1,真的就只是指向了下一个字节,而 C 中 + 1 或者 ++ 考虑了数据类型的长度,会自动指向当前值结尾后的下一个字节(或者说,有可能就是下一个值的开始)。如果 go 中要想实现同样的效果,可以使用 unsafe.Sizeof 方法:

unsafe.Pointer(uintptr(unsafe.Pointer(&p) + unsafe.Sizeof(p)))

最后,另外一种常用的指针操作是转换指针类型。这也可以利用 unsafe 包来实现:

var a int64 = 1
(*int8)(unsafe.Pointer(&a))

如果你没有遇到过需要转换指针类型的需求,可以看看这个项目(端口扫描工具),其中构建 IP 协议首部的代码,就用到了指针类型转换。

【相关推荐:Go视频教程编程教学

Atas ialah kandungan terperinci Apakah operasi pada penunjuk dalam bahasa go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn