Maison > Article > développement back-end > Quelles sont les opérations sur les pointeurs en langage Go ?
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.
L'environnement d'exploitation de ce tutoriel : système Windows 7, GO version 1.18, ordinateur Dell G3.
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.
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
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 enlangage 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.
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的类型为TParmi eux :
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 }
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.
- 但实际上,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 协议首部的代码,就用到了指针类型转换。
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!