Maison  >  Article  >  développement back-end  >  Quelles sont les opérations sur les pointeurs en langage Go ?

Quelles sont les opérations sur les pointeurs en langage Go ?

青灯夜游
青灯夜游original
2023-01-04 10:30:293545parcourir

Le langage Go n'a pas d'arithmétique de pointeur. La syntaxe du langage go ne prend pas en charge l'arithmétique des pointeurs, et tous les pointeurs sont utilisés dans une plage contrôlable ; mais en fait, le langage go peut utiliser la méthode Pointer() du package unsafe pour convertir les pointeurs en numéros de type uintptr pour implémenter indirectement. arithmétique du pointeur.

Quelles sont les opérations sur les pointeurs en langage Go ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, GO version 1.18, ordinateur Dell G3.

Qu'est-ce qu'un pointeur exactement ?

La mémoire est une série d'unités de stockage avec des numéros de série. Les variables sont des surnoms attribués par le compilateur aux adresses mémoire. Alors, que sont les pointeurs ?

Un pointeur est une valeur qui pointe vers une autre variable d'adresse mémoire

Le pointeur pointe vers l'adresse mémoire de la variable, et le pointeur est comme l'adresse mémoire de la valeur de la variable

Jetons un coup d'œil à un code extrait

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

Dans la fonction principale Dans la première ligne, nous définissons une nouvelle variable a et lui attribuons une valeur de 200. Ensuite, nous définissons une variable b et attribuons l'adresse de la variable a à b. Nous ne connaissons pas l'adresse de stockage exacte de a, mais nous pouvons toujours stocker l'adresse de a dans la variable b.

Quelles sont les opérations sur les pointeurs en langage Go ?

Quelles sont les opérations sur les pointeurs en langage Go ?

En raison de la nature fortement typée de Go, la troisième ligne de code est peut-être la plus intrusive b contient l'adresse de la variable a, mais nous voulons incrémenter la valeur stockée dans la variable a. .

De cette façon, nous devons déréférencer b et plutôt faire référence à a par b en suivant le pointeur.
Ensuite, nous ajoutons 1 à la valeur et la stockons à l'adresse mémoire stockée dans b.

La dernière ligne imprime la valeur de a. Vous pouvez voir que la valeur de a a augmenté à 201

Quelles sont les opérations sur les pointeurs en langage Go ?

Quelles sont les opérations sur les pointeurs en langage Go ?

Les paramètres de fonction dans le langage Go sont tous des copies de valeur Quand nous le voulons. pour modifier Quand une certaine variable, nous pouvons créer un pointeur variable pointant vers l'adresse de la variable.

Différent des pointeurs en C/C++, les pointeurs en

langage Go ne peuvent pas être décalés et utilisés, et sont des pointeurs sûrs.

Pour comprendre les pointeurs en langage Go, vous devez d'abord connaître trois concepts :

Adresse du pointeur, type de pointeur et valeur du pointeur.

Adresse du pointeur et type de pointeur

Les opérations du pointeur en langage Go sont très simples. Vous n'avez qu'à mémoriser deux symboles : & (obtenir l'adresse) et * (obtenir la valeur en fonction de l'adresse).

Chaque variable a une adresse au moment de l'exécution, qui représente l'emplacement de la variable en mémoire. Dans le langage Go, le caractère & est utilisé devant la variable pour "obtenir l'adresse" de la variable.

La syntaxe pour prendre un pointeur de variable est la suivante :

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

Parmi eux :

  • v : La variable représentant l'adresse en cours de prise, le type est T

  • ptr : La variable utilisée pour recevoir le adresse, le type de ptr est * T est appelé le type de pointeur de T. * signifie pointeur.

Quelles sont les opérations sur les pointeurs en langage 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
}

Opérateur de pointeur

1. Lorsque l'opérateur pointeur est une lvalue, on peut mettre à jour l'état de l'objet cible lorsqu'il s'agit d'une rvalue, c'est pour obtenir l'état de la cible ; .

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

0xc000040780 30

2. Les types de pointeurs prennent en charge les opérateurs d'égalité, mais ne peuvent pas effectuer d'addition, de soustraction et de conversion de type. Deux pointeurs sont égaux s’ils pointent vers la même adresse ou s’ils sont tous deux nuls.

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)   //指向同一地址
}
Vous pouvez utiliser unsafe.Pointer pour convertir le pointeur en uintptr, puis effectuer des opérations d'addition et de soustraction, mais cela peut provoquer un accès illégal.

Arithmétique des pointeurs

Dans de nombreux programmes Golang, bien que des pointeurs soient utilisés, les pointeurs ne sont ni ajoutés ni soustraits, ce qui est très différent des programmes C. L'outil d'apprentissage d'introduction officiel de Golang (

go tour) indique même que Go ne prend pas en charge l'arithmétique des pointeurs. Bien que ce ne soit pas réellement le cas, il semble que je n'ai jamais vu d'arithmétique de pointeur dans les programmes go ordinaires (enfin, je sais que vous voulez écrire des programmes inhabituels).

  • 但实际上,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视频教程编程教学

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn