Pointeur (programmation informatique)
AdaEdit
Ada est un langage fortement typé dans lequel tous les pointeurs sont tapés et seules les conversions de type sécurisées sont autorisées. Tous les pointeurs sont par défaut initialisés à null
, et toute tentative d’accès aux données via un pointeur null
provoque le déclenchement d’une exception. Les pointeurs dans Ada sont appelés types d’accès. Ada 83 n’autorisait pas l’arithmétique sur les types d’accès (bien que de nombreux fournisseurs de compilateurs l’aient fourni comme une fonctionnalité non standard), mais Ada 95 prend en charge l’arithmétique « sûre » sur les types d’accès via le package System.Storage_Elements
.
BASICEdit
Plusieurs anciennes versions de BASIC pour la plate-forme Windows prenaient en charge STRPTR () pour renvoyer l’adresse d’une chaîne, et pour VARPTR () pour renvoyer l’adresse de une variable. Visual Basic 5 prenait également en charge OBJPTR () pour renvoyer l’adresse d’une interface d’objet et pour un opérateur ADDRESSOF pour renvoyer l’adresse d’une fonction. Les types de tous ces éléments sont des entiers, mais leurs valeurs sont équivalentes à ceux détenus par des types de pointeurs.
Les nouveaux dialectes de BASIC, tels que FreeBASIC ou BlitzMax, ont cependant des implémentations exhaustives de pointeurs. Dans FreeBASIC, l’arithmétique sur les pointeurs ANY
équivalent à C « s void*
) sont traités comme si le pointeur ANY
avait une largeur d’octet. Les pointeurs ANY
ne peuvent pas être déréférencés, comme en C. De plus, la conversion entre les pointeurs de ANY
et de tout autre type « ne générera aucun avertissement.
dim as integer f = 257dim as any ptr g = @fdim as integer ptr i = gassert(*i = 257)assert( (g + 4) = (@f + 1) )
Edition C et C ++
En C et C ++, les pointeurs sont des variables qui stockent des adresses et peut être nul. Chaque pointeur a un type sur lequel il pointe, mais on peut effectuer librement un cast entre les types de pointeur (mais pas entre un pointeur de fonction et un pointeur d’objet). Un type de pointeur spécial appelé « pointeur void » permet de pointer vers n’importe quel (non -function), mais est limité par le fait qu’il ne peut pas être déréférencé directement (il doit être casté). L’adresse elle-même peut souvent être directement manipulée en jetant un pointeur vers et depuis un type intégral de taille suffisante, bien que les résultats soient définis par l’implémentation et puissent en effet provoquer un comportement indéfini; alors que les normes C antérieures n’avaient pas de type intégral garanti suffisamment grand, C99 spécifie le nom de uintptr_t
typedef défini dans <stdint.h>
, mais une implémentation n’a pas besoin de le fournir.
C ++ prend entièrement en charge les pointeurs C et le typage C. Il prend également en charge un nouveau groupe d’opérateurs de transtypage pour aider à capturer certains casts dangereux involontaires au moment de la compilation. Depuis C ++ 11, la bibliothèque standard C ++ fournit également des pointeurs intelligents (unique_ptr
, shared_ptr
et weak_ptr
) qui peut être utilisé dans certaines situations comme une alternative plus sûre aux pointeurs C primitifs. C ++ prend également en charge une autre forme de référence, assez différente d’un pointeur, appelée simplement un type de référence ou de référence.
Arithmétique du pointeur, c’est-à-dire la possibilité de modifier l’adresse cible d’un pointeur avec des opérations arithmétiques (comme ainsi que les comparaisons de magnitude), est limité par la norme de langage pour rester dans les limites d’un seul objet de tableau (ou juste après), et invoquera autrement un comportement indéfini. L’ajout ou la soustraction d’un pointeur le déplace d’un multiple de la taille de son type de données. Par exemple, l’ajout de 1 à un pointeur sur des valeurs entières de 4 octets incrémentera l’adresse d’octet pointée du pointeur de 4. Cela a pour effet d’incrémenter le pointeur pour qu’il pointe sur l’élément suivant dans un élément contigu tableau d’entiers – ce qui est souvent le résultat attendu. L’arithmétique du pointeur ne peut pas être effectuée sur les pointeurs void
car le type void n’a pas de taille, et donc l’adresse pointée ne peut pas être ajoutée, bien que gcc et d’autres compilateurs effectueront l’arithmétique d’octet sur void*
comme une extension non standard, en la traitant comme si elle était char *
.
L’arithmétique des pointeurs fournit au programmeur un manière unique de traiter différents types: ajouter et soustraire le nombre d’éléments requis au lieu du décalage réel en octets. (L’arithmétique du pointeur avec des pointeurs char *
utilise des décalages d’octets, car sizeof(char)
est égal à 1 par définition.) En particulier, la définition C déclare explicitement que le la syntaxe a
, qui est le n
-ème élément du tableau a
, est équivalente à *(a + n)
, qui est le contenu de l’élément pointé par a + n
. Cela implique que n
équivaut à a
, et que l’on peut écrire, par exemple, a
ou 3
aussi bien pour accéder au quatrième élément d’un tableau a
.
Bien que puissante, l’arithmétique des pointeurs peut être une source de bogues informatiques. Cela a tendance à confondre les programmeurs novices, les forçant à entrer dans des contextes différents: une expression peut être une arithmétique ordinaire ou une arithmétique à pointeur, et parfois il est facile de confondre l’une avec l’autre. En réponse à cela, de nombreux langages informatiques modernes de haut niveau (par exemple Java) ne permettent pas d’accéder directement à la mémoire à l’aide d’adresses. En outre, le dialecte C sûr Cyclone résout de nombreux problèmes liés aux pointeurs. Consultez le langage de programmation C pour plus de détails.
Le pointeur void
, ou void*
, est pris en charge dans ANSI C et C ++ en tant que type de pointeur générique. Un pointeur vers void
peut stocker l’adresse de n’importe quel objet (pas de fonction) et, en C, est implicitement converti en tout autre type de pointeur d’objet lors de l’affectation, mais il doit être explicitement converti if dereferenced.K & RC a utilisé char*
pour le but du « pointeur indépendant du type » (avant ANSI C).
C ++ ne permet pas la conversion implicite de void*
en d’autres types de pointeurs, même dans les affectations. Il s’agissait d’une décision de conception pour éviter les transtypages imprudents et même involontaires, bien que la plupart des compilateurs ne produisent que des avertissements , pas d’erreurs, lorsque vous rencontrez d’autres casts.
En C ++, il n’y a pas de void&
(référence à void) pour compléter void*
(pointeur vers void), car les références se comportent comme des alias des variables vers lesquelles elles pointent, et il ne peut jamais y avoir de variable dont le type est void
.
Présentation de la syntaxe des déclarations de pointeurModifier
Ces déclarations de pointeur c sur la plupart des variantes de déclarations de pointeur. Bien sûr, il est possible d’avoir des pointeurs triples, mais les principes fondamentaux d’un pointeur triple existent déjà dans un pointeur double.
Le () et ont une priorité plus élevée que *.
C # Edit
Dans le langage de programmation C #, les pointeurs ne sont supportés que sous certaines conditions: tout bloc de code comprenant des pointeurs doit être marqué du mot-clé unsafe
. Ces blocs nécessitent généralement des autorisations de sécurité plus élevées pour être autorisés à s’exécuter. La syntaxe est essentiellement la même qu’en C ++, et l’adresse pointée peut être de la mémoire gérée ou non gérée. Cependant, les pointeurs vers la mémoire gérée (tout pointeur vers un objet géré) doivent être déclarés à l’aide du mot-clé fixed
, qui empêche le garbage collector de déplacer l’objet pointé dans le cadre de la gestion de la mémoire pendant que le le pointeur est dans la portée, gardant ainsi l’adresse du pointeur valide.
Une exception à cela est l’utilisation de la structure IntPtr
, qui est un équivalent géré en toute sécurité à int*
, et ne nécessite pas de code non sécurisé. Ce type est souvent renvoyé lors de l’utilisation de méthodes du System.Runtime.InteropServices
, par exemple:
Le framework .NET comprend de nombreuses classes et méthodes dans le System
et System.Runtime.InteropServices
espaces de noms (tels que la classe Marshal
) qui convertissent les types .NET (par exemple, System.String
) vers et depuis de nombreux types et pointeurs non gérés (par exemple, LPWSTR
ou void*
) pour autoriser communication avec du code non géré. La plupart de ces méthodes ont les mêmes exigences d’autorisation de sécurité que le code non managé, car elles peuvent affecter des emplacements arbitraires en mémoire.
COBOLEdit
Le langage de programmation COBOL prend en charge les pointeurs vers des variables. Les objets de données primitifs ou de groupe (enregistrement) déclarés dans le LINKAGE SECTION
d’un programme sont intrinsèquement basés sur des pointeurs, où la seule mémoire allouée dans le programme est l’espace pour l’adresse de l’élément de données ( généralement un seul mot de mémoire). Dans le code source du programme, ces éléments de données sont utilisés comme toute autre variable WORKING-STORAGE
, mais leur contenu est implicitement accessible indirectement via leurs pointeurs LINKAGE
.
L’espace mémoire pour chaque objet de données pointé est généralement alloué dynamiquement à l’aide d’instructions externes CALL
ou via des constructions de langage étendu intégrées telles que ou EXEC SQL
.
Les versions étendues de COBOL fournissent également des variables de pointeur déclarées avec USAGE
Clauses IS
POINTER
. Les valeurs de ces variables de pointeur sont établies et modifiées à l’aide d’instructions SET
et SET
ADDRESS
.
Certaines versions étendues de COBOL fournissent également des variables PROCEDURE-POINTER
, qui sont capables de stocker les adresses du code exécutable.
PL / IEdit
Le langage PL / I fournit un support complet pour les pointeurs vers tous les types de données (y compris les pointeurs vers les structures), la récursivité, le multitâche, la gestion des chaînes et les fonctions intégrées étendues.PL / I était un pas en avant par rapport aux langages de programmation de l’époque. Les pointeurs PL / I ne sont pas typés et, par conséquent, aucune conversion n’est requise pour le déréférencement ou l’affectation de pointeurs. La syntaxe de déclaration d’un pointeur est DECLARE xxx POINTER;
, qui déclare un pointeur nommé « xxx ». Les pointeurs sont utilisés avec les variables BASED
. Une variable basée peut être déclarée avec un localisateur par défaut (DECLARE xxx BASED(ppp);
ou sans (DECLARE xxx BASED;
), où xxx est une variable basée, qui peut être une variable d’élément, une structure ou un tableau, et ppp est le pointeur par défaut). Une telle variable peut être une adresse sans référence de pointeur explicite (xxx=1;
, ou peut être adressée avec une référence explicite au localisateur par défaut (ppp), ou à tout autre pointeur (qqq->xxx=1;
).
L’arithmétique des pointeurs ne fait pas partie du standard PL / I, mais de nombreux compilateurs autorisent les expressions de la forme ptr = ptr±expression
. IBM PL / I dispose également de la fonction intégrée PTRADD
pour effectuer l’arithmétique. L’arithmétique du pointeur est toujours effectuée en octets.
Les compilateurs IBM Enterprise PL / I ont un nouvelle forme de pointeur typé appelé HANDLE
.
DEdit
Le langage de programmation D est un dérivé de C et C ++ qui prend entièrement en charge C pointeurs et transtypage C.
EiffelEdit
Le langage orienté objet Eiffel utilise une sémantique de valeur et de référence sans arithmétique de pointeur. Néanmoins, des classes de pointeur sont fournies. gestion de la mémoire, int avec des logiciels non-Eiffel et d’autres fonctionnalités.
FortranEdit
Fortran-90 a introduit une capacité de pointeur fortement typé. Les pointeurs Fortran contiennent plus qu’une simple adresse mémoire. Ils encapsulent également les limites inférieure et supérieure des dimensions de tableau, des foulées (par exemple, pour prendre en charge des sections de tableau arbitraires) et d’autres métadonnées. Un opérateur d’association, =>
est utilisé pour associer un POINTER
à une variable qui a un TARGET
attribut. L’instruction Fortran-90 ALLOCATE
peut également être utilisée pour associer un pointeur à un bloc de mémoire. Par exemple, le code suivant peut être utilisé pour définir et créer une structure de liste chaînée:
Fortran-2003 ajoute la prise en charge des pointeurs de procédure. De plus, dans le cadre de la fonctionnalité d’interopérabilité C, Fortran-2003 prend en charge des fonctions intrinsèques pour convertir des pointeurs de style C en pointeurs Fortran et inversement.
GoEdit
Go a des pointeurs. Sa syntaxe de déclaration est équivalente à celle de C, mais écrite dans le sens inverse, se terminant par le type. Contrairement à C, Go a garbage collection et interdit l’arithmétique des pointeurs. Les types de référence, comme en C ++, n’existent pas. Certains types intégrés, comme les cartes et les canaux, sont encadrés (c’est-à-dire qu’ils sont en interne des pointeurs vers des structures mutables) et sont initialisés à l’aide de la fonction make
. Dans une approche de la syntaxe unifiée entre pointeurs et non-pointeurs, l’opérateur flèche (->
) a été abandonné: l’opérateur point sur un pointeur fait référence au champ ou à la méthode de l’objet déréférencé . Ceci, cependant, ne fonctionne qu’avec 1 niveau d’indirection.
JavaEdit
Contrairement à C, C ++ ou Pascal, il n’y a pas de représentation explicite des pointeurs en Java. Au lieu de cela, des structures de données plus complexes telles que des objets et des tableaux sont implémentées à l’aide de références. Le langage ne fournit aucun opérateur de manipulation de pointeur explicite. Cependant, il est toujours possible pour le code de tenter de déréférencer une référence nulle (pointeur nul), ce qui entraîne la levée d’une exception d’exécution. L’espace occupé par les objets mémoire non référencés est récupéré automatiquement par garbage collection au moment de l’exécution.
Modula-2Edit
Les pointeurs sont implémentés comme en Pascal, tout comme VAR
dans les appels de procédure. Modula-2 est encore plus fortement typé que Pascal, avec moins de moyens d’échapper au système de types. Certaines des variantes de Modula-2 (comme Modula-3) incluent le ramasse-miettes.
OberonEdit
Tout comme avec Modula-2, des pointeurs sont disponibles. Il y a encore moins de façons d’échapper au système de type et donc Oberon et ses variantes sont toujours plus sûrs en ce qui concerne les pointeurs que Modula-2 ou ses variantes. Comme avec Modula-3, le garbage collection fait partie de la spécification du langage.
PascalEdit
Contrairement à de nombreux langages qui comportent des pointeurs, le Pascal ISO standard permet uniquement aux pointeurs de référencer des variables créées dynamiquement qui sont anonymes et ne leur permettent pas de référencer des variables statiques ou locales standard. Il n’a pas d’arithmétique de pointeur. Les pointeurs doivent également avoir un type associé et un pointeur vers un type n’est pas compatible avec un pointeur vers un autre type (par exemple, un pointeur vers un caractère n’est pas compatible avec un pointeur vers un entier).Cela permet d’éliminer les problèmes de sécurité de type inhérents aux autres implémentations de pointeurs, en particulier ceux utilisés pour PL / I ou C.Il supprime également certains risques causés par des pointeurs suspendus, mais la possibilité de libérer dynamiquement l’espace référencé en utilisant le dispose
(qui a le même effet que la fonction de bibliothèque free
trouvée en C) signifie que le risque de balancer des pointeurs n’a pas été entièrement éliminé.
Cependant, dans certaines implémentations de compilateurs Pascal (ou dérivés) commerciaux et open source – comme Free Pascal, Turbo Pascal ou Object Pascal dans Embarcadero Delphi – un pointeur est autorisé à référencer des variables statiques ou locales standard et peut être transtyper d’un type de pointeur à un autre. De plus, l’arithmétique du pointeur est illimitée: l’ajout ou la soustraction d’un pointeur le déplace de ce nombre d’octets dans les deux sens, mais en utilisant Inc
ou Dec
les procédures standard avec elle déplace le pointeur de la taille du type de données vers lequel il est déclaré. Un pointeur non typé est également fourni sous le nom Pointer
, qui est compatible avec d’autres types de pointeurs.