Recherchez sur tout Techno-Science.net
       
Techno-Science.net : Suivez l'actualité des sciences et des technologies, découvrez, commentez
 A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | +
Pointeur (programmation)

Un pointeur est en programmation une variable contenant une adresse mémoire.

Utilité

La notion de pointeur reflète l'utilisation différente que l'on peut faire d'un nombre entier, à savoir indiquer une adresse (Les adresses forment une notion importante en communication, elles permettent à une entité de s'adresser à une autre parmi un ensemble d'entités. Pour qu'il n'y...) mémoire (D'une manière générale, la mémoire est le stockage de l'information. C'est aussi le souvenir d'une information.). Cette utilisation est très différente (En mathématiques, la différente est définie en théorie algébrique des nombres pour mesurer l'éventuel défaut de...) d'une utilisation arithmétique (L'arithmétique est une branche des mathématiques qui comprend la partie de la théorie des nombres qui utilise des méthodes de la géométrie algébrique et de la théorie des groupes. On l'appelle plus généralement la...), d'où la création de registres processeurs spécifiques (les registres d'adresse) et d'un type de donnée (Dans les technologies de l'information (TI), une donnée est une description élémentaire, souvent codée, d'une chose, d'une transaction d'affaire, d'un événement, etc.) spécifique dans les langages de programmations.

Les pointeurs "typés", le type le plus répandu de pointeur actuellement, sont apparus avec le langage C, qui a ajouté un typage sur les données pointées par le pointeur. Quand on incrémente un tel pointeur, il n'est en fait pas forcément incrémenté de un, mais de la taille du type pointé.

L'utilisation des pointeurs permet d'avoir accès à la couche basse de l'ordinateur (Un ordinateur est une machine dotée d'une unité de traitement lui permettant d'exécuter des programmes enregistrés. C'est un ensemble de circuits...), un accès direct (Un logiciel fait un accès direct (aussi appelé accès aléatoire) à un élément (par exemple, un enregistrement d’un fichier) lorsqu’il écrit ou qu’il...) à la mémoire. On peut littéralement se déplacer de case mémoire en case mémoire. Cette technique permet d'effectuer des optimisations sur l'utilisation de la mémoire ou la performance en terme de vitesse (On distingue :).

Les pointeurs sont entre autre utilisés pour stocker les adresses des zones mémoires allouées dynamiquement par l'application. Si on alloue un bloc de taille T et qu'on reçoit l'adresse A en retour, cela veut dire que le bloc occupe la mémoire à partir de l'adresse A jusqu'à l'adresse A+T-1.

Dans les langages de plus haut niveau, l'utilisation des pointeurs est supprimée, au profit des références et des tableaux dynamiques gérés par le compilateur. Les références remplissent certaines fonctions des pointeurs en supprimant l'accès à la mémoire. Cela évite beaucoup de problèmes, en contrepartie certaines utilisations et optimisations ne sont plus possibles.

Complexification

L'utilisation des pointeurs est très puissante dans certains langages. Cette puissance (Le mot puissance est employé dans plusieurs domaines avec une signification particulière :) et surtout le fait que l'on touche directement à la mémoire sans aucun contrôle (Le mot contrôle peut avoir plusieurs sens. Il peut être employé comme synonyme d'examen, de vérification et de maîtrise.), complexifie le développement d'une application.

Si l'on ne fait pas attention et que l'on accède à une zone mémoire qui ne nous est pas allouée, le processeur (Le processeur, ou CPU (de l'anglais Central Processing Unit, « Unité centrale de traitement »), est le composant de l'ordinateur qui exécute les programmes informatiques. Avec la...) via le système d'exploitation génèrera une erreur de segmentation (Une erreur de segmentation (en anglais segmentation fault, parfois appelé en abrégé segfault), est un plantage d'une application qui a tenté d'accéder à un emplacement mémoire qui ne lui était pas alloué.) qui provoquera une exception voire fera planter l'application. De plus, comme les allocations mémoire sont réalisées en partie par le développeur (En informatique, un développeur (ou programmeur) est un informaticien qui réalise des logiciels en créant des algorithmes et en les mettant en œuvre dans un langage de programmation.), il doit également se charger de la libération de la mémoire lorsqu'il n'en a plus besoin (Les besoins se situent au niveau de l'interaction entre l'individu et l'environnement. Il est souvent fait un classement des besoins humains en trois grandes catégories : les besoins primaires, les besoins secondaires et les besoins...), au risque de voir une fuite mémoire apparaître.

Tous ces inconvénients obligent le développeur à prendre en charge (La charge utile (payload en anglais ; la charge payante) représente ce qui est effectivement transporté par un moyen de transport donné, et qui donne lieu à un paiement ou...) des choses supplémentaires, complexifiant ainsi l'application et pouvant ajouter des bugs.

Langages utilisant les pointeurs

Les pointeurs sont, entre autres, utilisés par le C, le C++, le Pascal, Ada, FreeBASIC, Fortran, C#, D, Modula-2 et Oberon.

Pointeurs en C et C++

Les deux principaux langages utilisant énormément les pointeurs sont le C et le C++. Dans ces langages, un pointeur est déclaré avec une étoile (Une étoile est un objet céleste émettant de la lumière de façon autonome, semblable à une énorme boule de plasma comme le Soleil, qui est l'étoile la plus proche de la Terre.) '*'. On récupère l'adresse d'une variable (En mathématiques et en logique, une variable est représentée par un symbole. Elle est utilisée pour marquer un rôle dans une formule, un prédicat ou un algorithme. En statistiques, une...) avec un et commercial '&'.

L'étoile, préposée, sert également à déréférencer l'adresse d'un pointeur. Autrement dit à avoir accès au contenu pointé par le pointeur.

Voici un petit exemple :

 
 int a = 2;       //Déclaration de la variable a de type int (entier) et initialisé avec 2 
 int * p = NULL (NULL est un mot clef présent dans de nombreux langages informatiques, et qui désigne l'état d'un pointeur qui n'a pas de cible ou d'une variable qui n'a pas de valeur. La notion de valeur ou de...);  //Déclaration d'un pointeur sur un int qui vaut NULL 
 p = &a ;         //l'adresse de a est affecté au pointeur p 
 //Actuellement a vaut 2 
 *p = 5;          //Déréférenciation de p, pour affecter 5 à la variable a 
 //Maintenant a vaut 5 
 

Pointeurs en Pascal

La syntaxe en Pascal est très similaire à celle en C et C++. Les pointeurs typés sont déclarés avec un chapeau '^' préposé au type pointé. On récupère l'adresse d'une variable avec une arobase '@'.

Le chapeau sert également à déréférencer l'adresse d'un pointeur, mais alors il est postposé. L'exemple ci-dessus s'écrit donc en Pascal ainsi :

 
 var a: integer;    { déclaration de la variable a de type integer (entier) } 
 p: ^integer;   { déclaration de la variable p de type pointeur sur entier } 
 begin 
 a:= 2;        { initialisation de a à 2 } 
 p:= @a;       { adresse de a affectée au pointeur p } 
 p^:= 5;       { déréférenciation de p, pour affecter 5 à la variable a } 
 end; 
 

Des types sont prédéfinis comme :

 
 type 
 pchar = ^char; 
 pinteger = ^integer; 
 

Arithmétique des pointeurs

On appelle arithmétique des pointeurs la possibilité de faire des opérations arithmétiques (incrémentation, décrémentation, addition (L'addition est une opération élémentaire, permettant notamment de décrire la réunion de quantités ou l'adjonction de grandeurs extensives de même nature, comme les longueurs, les aires, ou les...) et soustraction) sur les pointeurs. Cela revient à effectuer un déplacement ( En géométrie, un déplacement est une similitude qui conserve les distances et les angles orientés. En psychanalyse, le déplacement est mécanisme de défense...) en mémoire.

La particularité de cette utilisation des pointeurs, est que l'on se déplace par saut de la taille mémoire du type de donnée (Dans les technologies de l'information, une donnée est une description élémentaire, souvent codée, d'une chose, d'une transaction, d'un...) pointé par le pointeur et non par octet (qui est la plus petit unité accessible).

En voici un exemple en C :

 
 char tab[] = {'t', 'a', 'b', '\0'}; 
 char * p1 = &tab[0]; 
 

Ici le pointeur p1, contient l'adresse du premier élément du tableau (Tableau peut avoir plusieurs sens suivant le contexte employé :) tab (ce qui est équivalent à p1 = tab). Si l'on déréférence p1, nous aurions donc le caractère 't'.

 
 p1 = p1 + 1; 
 

En faisant cela, p1 ne pointe plus sur le caractère 't', mais sur 'a'. Dans cette exemple, le déplacement en mémoire a été de un octet (car le type char vaut toujours un octet). Mais si le tableau avait contenu des données de type long, le déplacement aurait été de quatre octets. Le déplacement se fait donc par saut de la taille mémoire du type de donnée pointé par le pointeur.

Exemple en Pascal

Encore une fois, la syntaxe en Pascal est très proche.

 
 const { les deux définitions sont équivalentes } 
 tab: array[0..3] of char = 'TAB'#0; 
 tab2: array[0..3] of char = ('T', 'A', 'B', #0); 
 var 
 p1: ^char; 
 begin 
 p1:= @tab[0];  { p1 pointe sur le 'T' } 
 inc(p1);        { p1 pointe sur le 'A' } 
 end. 
 

Une différence importante pourtant reste, c'est qu'on ne peut que incrémenter et décrémenter un pointeur typé. Pour faire une addition proprement dite, il faut convertir en entier d'abord :

 
 begin 
 p1:= @tab[0];                 { p1 pointe sur le 'T' } 
 p1:= ptr( integer(p1) + 2 );  { p1 pointe sur le 'B' } 
 end. 
 

Dans ce cas-là, il faut prendre soi-même en charge la multiplication (La multiplication est l'une des quatre opérations de l'arithmétique élémentaire avec l'addition, la soustraction et la division .) éventuelle par la taille du type des données pointées.

Pointeur sur une fonction

Les pointeurs peuvent également contenir l'adresse d'une fonction. Cette dernière peut ainsi être passée en paramètre (Un paramètre est au sens large un élément d'information à prendre en compte pour prendre une décision ou pour effectuer un calcul.) à une autre fonction et être appelée.

Exemple en C

Voici un exemple en C, de la déclaration d'un pointeur qui contient successivement les fonctions fonction_1() et fonction_2() :

 
 void fonction_1() { 
 printf("affiche fonction_1"); 
 } 
 void fonction_2() { 
 printf("affiche fonction_2"); 
 } 
 int main (La main est l’organe préhensile effecteur situé à l’extrémité de l’avant-bras et relié à ce dernier par le poignet. C'est un organe destiné à saisir et...)() { 
 void (*fonction)(); 
 fonction = fonction_1; 
 fonction(); 
 fonction = fonction_2; 
 fonction(); 
 } 
 

Ce code va produire la sortie suivante : affiche fonction_1affiche fonction_2

Même exemple en Pascal

 
 procedure fonction_1; 
 begin 
 writeln('affiche fonction_1'); 
 end; 
 procedure fonction_2; 
 begin 
 writeln('affiche fonction_2'); 
 end; 
 var 
 fonc: procedure; 
 begin  { bloc principal } 
 @fonc:= @fonction_1; 
 fonc; 
 @fonc:= @fonction_2; 
 fonc; 
 end. 
 
Source: Wikipédia publiée sous licence CC-BY-SA 3.0.

Vous pouvez soumettre une modification à cette définition sur cette page. La liste des auteurs de cet article est disponible ici.
Page générée en 0.069 seconde(s) - site hébergé chez Amen
Ce site fait l'objet d'une déclaration à la CNIL sous le numéro de dossier 1037632
Ce site est édité par Techno-Science.net - Informations légales