Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Langage C++
  3. Pointeurs
Extrait - Langage C++ De l'héritage C au C++ moderne (avec programmes d'illustration) (2e édition)
Extraits du livre
Langage C++ De l'héritage C au C++ moderne (avec programmes d'illustration) (2e édition) Revenir à la page d'achat du livre

Pointeurs

Principes généraux

En C comme en C++, tous les objets informatiques, qu’il s’agisse de variables, de fonctions, de tableaux, de structures, etc., correspondent à une inscription localisée quelque part dans la mémoire principale, dénommée également mémoire vive ou RAM. En un mot, chaque objet a une "adresse" dans la mémoire principale. Cette adresse est un nombre et il correspond à un emplacement de la mémoire.

1. Adresse et mémoire

La mémoire est construite sur le base d’un entrelacement d’octets. En 32 bits, il s’agit d’un entrelacement de quatre octets en quatre octets consécutifs. À partir de l’octet, qui est la plus petite unité de mémoire adressable (l’octet a 8 bits et correspond en C/C++ au type char), la mémoire est constituée d’emplacements dits "mots" de quatre octets, 32 bits, dont l’adresse est toujours un nombre multiple de quatre, généralement en hexadécimal.

Voici une représentation de ce principe en partant de l’adresse 128 avec une progression de 4 en 4, ici en décimal pour simplifier.

images/01RI17.png

Dans un programme, lorsqu’une variable quelconque est déclarée, une adresse mémoire lui est automatiquement affectée à la compilation. Soit par exemple trois variables dans un programme :

unsigned C=255; 
int A=256, B=129; 

Admettons que l’adresse de C soit 128, l’adresse de A pourrait être 132 et l’adresse de B 144, ce qui donnerait en mémoire :

images/02RI17.png

La variable B a pour valeur 129, soit 10000001 en binaire, et est à l’adresse 144.

La variable A a pour valeur 256, 100000000 en binaire, et est à l’adresse 132.

La variable C a pour valeur 255, 11111111 en binaire, et est à...

Hérité du C

1. Déclarer un pointeur dans un programme

Pour déclarer un pointeur, c’est-à-dire pour avoir un pointeur dans un programme, il faut :

  • le type de l’objet sur lequel pointer ;

  • l’opérateur * (à gauche du nom du pointeur) ;

  • un nom (identificateur) pour le pointeur.

Par exemple :

char *c;        // déclare un pointeur sur char 
int *i, *j;     // déclare deux pointeurs sur int 
float *f1,*f2;  // déclare deux pointeurs sur float 

c est un pointeur de type char* : il peut contenir des adresses de char.

i et j sont deux pointeurs de type int*, ils peuvent contenir des adresses de int.

f1 et f2 sont deux pointeurs de type float*, ils peuvent contenir des adresses de float.

Avec des structures, le principe est identique :

struct player{    // définition du type player  
    int x,y;  
    int dx,dy;  
}; 
 
player *p;             // déclare un pointeur player 

p est un pointeur de type player* et p peut contenir des adresses de structures player.

2. Opérateur adresse : &

L’opérateur & accolé à gauche d’un objet quelconque dans un programme retourne son adresse. Par exemple :

int k; 
   &k         // cette expression vaut l'adresse mémoire 
              // de la variable de k 

Toute adresse est une valeur pointeur : si k est un objet de type T alors &k est de type pointeur sur T.

Notons que k doit être ce que l’on appelle une lvalue, c’est-à-dire...

Apports du C++

1. Un souci de rigueur

a. Plus de rigueur

La pratique du C suppose beaucoup de vigilance de la part du programmeur surtout pour ce qui concerne la gestion des pointeurs. Ils peuvent être des sources d’erreurs et de bugs difficiles à trouver. Il suffit par exemple qu’une étoile manque quelque part dans un code de plusieurs milliers de lignes pour que le programme plante de temps en temps, une fois tous les six mois, sans que l’on comprenne pourquoi. De telles erreurs sont indétectables par le compilateur parce que ce ne sont pas des erreurs de syntaxe, ce sont des erreurs d’écriture avec une syntaxe plausible pour la machine. C’est ce qui vaut au langage C sa réputation de langage difficile : le programmeur C se doit d’être très rigoureux et solide lors de ses nombreuses manipulations de pointeurs. 

Le C++ conserve les pointeurs avec l’accès direct à la mémoire et il en augmente même les possibilités, mais à chaque fois que c’est possible, il intègre dans sa syntaxe des éléments de sécurisation qui proviennent initialement de la pratique et de l’expérience du C.

Voici par exemple une source d’erreur possible en C mais impossible en C++. Si dans un programme on écrit quelque chose comme :

char a = 'a';      // droit pour 1 octet 
double*d = &a;     // mais accès sur 8 octets ! 
    *d = 1000.75; 

En C, le compilateur signale une incompatibilité entre le type char* et le type double sous la forme d’un warning, mais il compile, et lorsqu’on lance le programme, il peut s’exécuter si la mémoire accédée par le pointeur est libre (sous Visual Studio, il y a néanmoins...