Historiquement, les pointeurs sont devenus la base du travail avec la mémoire en langage C et ont fourni un mécanisme flexible pour un accès efficace aux éléments du tableau et aux structures dynamiques. Cependant, la syntaxe et la sémantique des pointeurs vers des tableaux et des tableaux de pointeurs provoquent souvent de la confusion.
Problème : les programmeurs débutants confondent souvent pointeur vers tableau (pointer to array) et tableau de pointeurs (array of pointers), ce qui entraîne une utilisation incorrecte de la mémoire, des erreurs de passation de paramètres et des erreurs de syntaxe difficile à construire.
Solution :
Exemple de déclaration et d'utilisation :
// Pointeur vers un tableau de 10 int : int (*p)[10]; int arr[10]; p = &arr; // Tableau de 10 pointeurs vers int int *ap[10]; for (int i = 0; i < 10; ++i) { ap[i] = &arr[i]; } // Comment obtenir un élément via le pointeur vers le tableau : (*p)[2] = 5; // le troisième élément de arr // Comment obtenir une valeur en utilisant le tableau de pointeurs : *ap[2] = 8; // le troisième élément de arr via ap
Caractéristiques clés :
**int p[10] et int (p)[10] sont-ils identiques ?
Non. int *p[10] est un tableau de 10 pointeurs vers int. int (*p)[10] est un pointeur vers un tableau de 10 int. Une grande confusion se crée sans parenthèses !
Exemple de code :
int arr[10]; int *p[10]; // tableau de pointeurs int (*q)[10] = &arr; // pointeur vers un tableau
*Peut-on librement assigner un pointeur normal vers int à une variable de type int (p)[10] ?
Non. un int * ordinaire pointe vers un seul élément, tandis que int (*p)[10] pointe vers un tableau de 10 entiers ; les types sont incompatibles sans conversion explicite.
Comment passer correctement un tableau en deux dimensions à une fonction ?
Il faut indiquer explicitement la taille de la deuxième dimension :
void foo(int a[][4], int n); // tableau de n lignes avec 4 éléments
ou utiliser un pointeur vers un tableau :
void bar(int (*a)[4], int n);
Un ingénieur déclare une variable comme int *p[10], essaie de lui assigner &arr, où arr est int arr[10] et essaie d'accéder comme à un tableau, ce qui entraîne une erreur de compilation ou un comportement invalide.
Avantages :
Inconvénients :
Un développeur utilise attentivement les parenthèses : int (*p)[10], comprend bien la différence, passe correctement les tableaux aux fonctions, utilise typedef pour simplifier les déclarations.
Avantages :
Inconvénients :