Assimiler la notion de pointeur en C

Creusons un peu le bas niveau.

Disclaimer

Ni diagramme, ni article académique. Pourtant, il faut bien de la théorie pour “parler C” mais essayons ici autre chose.

Parlons tableaux

Les tableaux (de l’anglais “arrays”) sont pratiques pour stocker de multiples valeurs:

#include <stdio.h>

int main () {
	int arr[] = {13,27,51};
	printf("%d\n", arr[2]);
	printf("%d\n", *(arr + 2));
	return 0;
}

Dans le code ci-dessus, arr[2] revient à *(arr + 2). Tous les langages dérivés du C, donc la plupart des langages de programmation très populaires, fonctionnent de cette façon.

Le lien avec les pointeurs C n’est pas évident à ce stade.

N.B.: *(arr + 2) stocke en fait l’adresse du premier élément dans le 3ème rang.

Parlons mémoire rapidement

Juste un ensemble de bytes au final.


Oui le langage informatique peut déclencher des associations d’idée bien grasses avec les “pointeurs”, “bytes” et autres “arrays” mais gardons notre calme.


Chaque byte se voit allouer une adresse réservée. Les programmes vont pouvoir y stocker des données.

RAM veut dire “random access memory”. C’est ce qui est utilisé chaque fois qu’on modifie ou execute quelque chose sur la machine, mais cela disparaît quand on éteint le poste. Pour pallier ce problème, on stocke les données dans des fichiers (hard disk), afin des les retrouver au prochain démarrage.

Parlons pointeurs dans la mémoire

Si on ajoute des variables, on demande en fait un certain espace mémoire dans la RAM. Ces bytes de mémoire sont comparables à des cellules individuelles qui, assemblées, constituent parfois de gigantesques tableaux.

Pointer vers une cellule en particulier nous permet d’accéder aux valeurs qu’elle contient. Les ordinateurs fonctionnant avec des schamés type 0/1, ces cellules vont contenir des représentations binaires de chaîne de caractères (string), entiers (integer), ou tout autre type de donnée valide.

N.B.: Résumé grossier.

Les pointeurs en tant qu’adresses

#include <stdio.h>

int main () {
	int number;
	number = 111;
	int* pointer = &number;
	printf("%p\n", pointer);
	return 0;
}

Le code ci-dessus demande un espace mémoire. Ce groupe de bytes est nommé ici “number”, et on y met la valeur “111”. Ensuite, on créé un pointeur de type entier qui va contenir l’adresse mémoire.

Si on exécute le programme, on obtiendra quelque chose comme 0x7ffeedfe58a8 mais qu’est-ce que cela signifie ?

A quoi servent les pointeurs ?

Le but est d’éviter de copier des variables encore et encore, chaque fois qu’on doit les utiliser. Comme on sait les localiser dans la mémoire, on peut les manipuler facilement, et tout changement sera appliqué partout où la variable est utilisée automatiquement.

C’est particulièrement utile avec les gros tableaux qui satureraient la mémoire s’ils étaient copiés à tort et à travers.

Fonctions de pointeur en C

En C, les “function pointers” sont un mécanisme de rappel (callback). On appelle du code lors d’un évènement précis, ce qui compense l’absence de représentation runtime.

Cela améliore la lisibilité du code aussi en évitant les if/else et autres switch imbriqués.

La syntaxe est assez étrange cependant :

<return_type> (*<pointer>) (args);

Conclusion

Nous avons à peine effleuré la théorie mais en espérant avoir dégrossi un sujet assez dense.

Le concept de “pointeur” est assez central en science informatique. L’apprendre et le maîtriser vous permettra de progresser en C à vitesse grand V.