Introduction
L'arithmétique des pointeurs est une fonctionnalité puissante en C qui vous permet de manipuler les adresses mémoire en ajoutant ou en soustrayant des valeurs. L'une des applications les plus courantes de l'arithmétique des pointeurs est la traversée de tableaux. En utilisant des pointeurs, nous pouvons parcourir efficacement les tableaux dans les deux sens, avant et arrière.
Dans ce lab (atelier), vous apprendrez à créer et à initialiser des tableaux, à configurer des pointeurs pour accéder aux éléments des tableaux et à utiliser l'arithmétique des pointeurs pour parcourir les tableaux. Cette technique est fondamentale en programmation C et constitue la base de nombreuses opérations avancées de manipulation de données.
Création d'un programme C de base
Commençons par créer un nouveau fichier C dans l'éditeur VSCode. Ce fichier contiendra notre programme principal pour la traversée de tableaux à l'aide de pointeurs.
Dans le WebIDE, localisez le panneau de l'Explorateur sur le côté gauche et accédez au répertoire
~/project.Cliquez avec le bouton droit sur le dossier
projectet sélectionnez "Nouveau fichier". Nommez le fichiermain.c.Copiez la structure de base d'un programme C suivante dans le fichier :
#include <stdio.h>
int main() {
printf("Array Traversal using Pointers\n");
return 0;
}
Enregistrez le fichier en appuyant sur Ctrl+S ou en utilisant Fichier > Enregistrer dans le menu.
Compilons et exécutons ce programme pour nous assurer que tout est correctement configuré. Ouvrez un terminal dans le WebIDE en sélectionnant Terminal > Nouveau terminal dans le menu, puis exécutez :
cd ~/project
gcc main.c -o main
./main
Vous devriez voir la sortie suivante :
Array Traversal using Pointers
Cela confirme que votre environnement de développement C fonctionne correctement. Dans les étapes suivantes, nous modifierons ce programme pour qu'il fonctionne avec des tableaux et des pointeurs.
Déclaration et initialisation de tableaux et de pointeurs
Dans cette étape, nous apprendrons à déclarer un tableau et un pointeur, qui sont les composants fondamentaux pour la traversée de tableaux à l'aide de pointeurs.
Compréhension des tableaux et des pointeurs
Un tableau en C est une collection d'éléments du même type stockés dans des emplacements mémoire contigus. Par exemple, un tableau d'entiers avec 5 éléments réservera de l'espace pour 5 entiers en mémoire, l'un après l'autre.
Un pointeur est une variable qui stocke l'adresse mémoire d'une autre variable. Nous pouvons utiliser des pointeurs pour accéder indirectement à la valeur stockée à un emplacement mémoire particulier.
Modifions notre fichier main.c pour inclure un tableau et un pointeur :
#include <stdio.h>
int main() {
printf("Array Traversal using Pointers\n\n");
// Declare and initialize an array of 5 integers
int arr[5] = {10, 20, 30, 40, 50};
// Declare a pointer of integer type
int *ptr;
// Print the array elements using array notation
printf("Array elements using array notation:\n");
for(int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
return 0;
}
Dans ce code :
- Nous avons déclaré un tableau d'entiers
arravec 5 éléments et l'avons initialisé avec les valeurs 10, 20, 30, 40 et 50. - Nous avons déclaré un pointeur d'entiers
ptrqui sera utilisé plus tard pour pointer vers les éléments du tableau. - Nous avons affiché les éléments du tableau en utilisant la notation traditionnelle des tableaux.
Compilez et exécutez le programme pour voir les éléments du tableau :
gcc main.c -o main
./main
Vous devriez voir la sortie suivante :
Array Traversal using Pointers
Array elements using array notation:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50
Dans l'étape suivante, nous connecterons le pointeur au tableau et accéderons aux éléments du tableau à l'aide du pointeur.
Liaison des pointeurs avec des tableaux et parcours en avant
Dans cette étape, nous établirons la connexion entre notre pointeur et le tableau, puis nous utiliserons le pointeur pour parcourir le tableau dans le sens avant.
Liaison d'un pointeur à un tableau
En C, le nom d'un tableau sans indice représente l'adresse du premier élément du tableau. Cela signifie que nous pouvons assigner directement cette adresse à une variable pointeur.
Modifions notre fichier main.c pour lier le pointeur au tableau et le parcourir :
#include <stdio.h>
int main() {
printf("Array Traversal using Pointers\n\n");
// Declare and initialize an array of 5 integers
int arr[5] = {10, 20, 30, 40, 50};
// Declare a pointer of integer type
int *ptr;
// Assign the address of the first element of the array to the pointer
ptr = arr; // This is equivalent to ptr = &arr[0]
// Print the array elements using array notation
printf("Array elements using array notation:\n");
for(int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
// Print the array elements using pointer notation
printf("\nArray elements using pointer notation (forward traversal):\n");
for(int i = 0; i < 5; i++) {
printf("*(ptr + %d) = %d\n", i, *(ptr + i));
}
return 0;
}
Dans ce code mis à jour :
- Nous avons assigné l'adresse du premier élément du tableau
arrau pointeurptr. - Nous avons ajouté une nouvelle boucle qui parcourt le tableau en utilisant l'arithmétique des pointeurs.
- L'expression
*(ptr + i)accède à la valeur située à l'emplacement mémoireptr + i. Lorsqueiest égal à 0, il s'agit du premier élément du tableau ; lorsqueiest égal à 1, il s'agit du deuxième élément, et ainsi de suite.
Compilez et exécutez le programme pour voir les résultats :
gcc main.c -o main
./main
Vous devriez voir la sortie suivante :
Array Traversal using Pointers
Array elements using array notation:
arr[0] = 10
arr[1] = 20
arr[2] = 30
arr[3] = 40
arr[4] = 50
Array elements using pointer notation (forward traversal):
*(ptr + 0) = 10
*(ptr + 1) = 20
*(ptr + 2) = 30
*(ptr + 3) = 40
*(ptr + 4) = 50
Remarquez que les deux méthodes produisent la même sortie. Cela démontre que l'arithmétique des pointeurs peut être utilisée pour accéder aux éléments d'un tableau tout comme l'indexation traditionnelle des tableaux.
Implémentation de l'incrémentation de pointeur pour le parcours de tableau
Dans l'étape précédente, nous avons accédé aux éléments d'un tableau en utilisant l'expression *(ptr + i). Bien que cela fonctionne parfaitement, le langage C propose un moyen plus concis de parcourir un tableau à l'aide de pointeurs : l'opérateur d'incrémentation (++).
Lorsque nous incrémentons un pointeur, il se déplace vers l'emplacement mémoire suivant en fonction de la taille du type de données vers lequel il pointe. Pour un pointeur d'entier, l'incrémenter le fait passer au prochain entier en mémoire.
Modifions notre fichier main.c pour utiliser l'incrémentation de pointeur pour la traversée du tableau :
#include <stdio.h>
int main() {
printf("Array Traversal using Pointers\n\n");
// Declare and initialize an array of 5 integers
int arr[5] = {10, 20, 30, 40, 50};
// Declare and initialize a pointer to the first element of the array
int *ptr = arr; // Same as ptr = &arr[0]
// Print the array elements using pointer incrementation
printf("Array elements using pointer incrementation:\n");
for(int i = 0; i < 5; i++) {
printf("*ptr = %d\n", *ptr);
ptr++; // Move the pointer to the next element
}
// Reset the pointer to the beginning of the array
ptr = arr;
// Print all elements in a single line using pointer incrementation
printf("\nAll elements in a single line: ");
for(int i = 0; i < 5; i++) {
printf("%d ", *ptr++); // Print and then increment
}
printf("\n");
return 0;
}
Dans ce code mis à jour :
- Nous initialisons le pointeur
ptrdirectement lors de sa déclaration. - À l'intérieur de la première boucle, nous utilisons
*ptrpour accéder à l'élément actuel, puisptr++pour passer à l'élément suivant. - Après la première boucle, nous réinitialisons
ptrpour qu'il pointe de nouveau au début du tableau. - Dans la deuxième boucle, nous utilisons l'opérateur d'incrémentation postfixée
*ptr++, qui utilise d'abord la valeur actuelle deptr, puis l'incrémente.
Compilez et exécutez le programme pour voir les résultats :
gcc main.c -o main
./main
Vous devriez voir la sortie suivante :
Array Traversal using Pointers
Array elements using pointer incrementation:
*ptr = 10
*ptr = 20
*ptr = 00
*ptr = 40
*ptr = 50
All elements in a single line: 10 20 30 40 50
Cela démontre comment utiliser l'incrémentation de pointeur pour parcourir un tableau. Le point clé est que ptr++ prend automatiquement en compte la taille du type de données lorsqu'il se déplace vers l'élément suivant.
Implémentation du parcours en arrière en utilisant la décrémentation de pointeur
Dans les étapes précédentes, nous avons parcouru le tableau dans le sens avant. Maintenant, apprenons à parcourir le tableau dans le sens inverse en utilisant la décrémentation de pointeur.
Pour la traversée en arrière, nous devons :
- Initialiser le pointeur pour qu'il pointe vers le dernier élément du tableau.
- Décrémenter le pointeur pour nous déplacer en arrière dans le tableau.
Modifions notre fichier main.c pour implémenter la traversée en arrière :
#include <stdio.h>
int main() {
printf("Array Traversal using Pointers\n\n");
// Declare and initialize an array of 5 integers
int arr[5] = {10, 20, 30, 40, 50};
// Forward traversal using pointer increment
int *ptr = arr;
printf("Forward traversal using pointer increment:\n");
for(int i = 0; i < 5; i++) {
printf("%d ", *ptr);
ptr++;
}
printf("\n\n");
// Backward traversal using pointer decrement
// Point to the last element of the array
ptr = &arr[4]; // or ptr = arr + 4
printf("Backward traversal using pointer decrement:\n");
for(int i = 0; i < 5; i++) {
printf("%d ", *ptr);
ptr--; // Move the pointer to the previous element
}
printf("\n\n");
// Alternative approach: Start from the last element and decrement in the loop condition
printf("Alternative backward traversal approach:\n");
for(ptr = &arr[4]; ptr >= arr; ptr--) {
printf("%d ", *ptr);
}
printf("\n");
return 0;
}
Dans ce code mis à jour :
- Nous effectuons d'abord une traversée en avant en utilisant l'incrémentation de pointeur.
- Pour la traversée en arrière, nous positionnons le pointeur sur le dernier élément du tableau en utilisant
ptr = &arr[4]. - À l'intérieur de la boucle, nous affichons l'élément actuel, puis nous décrémentons le pointeur en utilisant
ptr--. - Nous montrons également une méthode alternative où la décrémentation fait partie de l'instruction de mise à jour de la boucle
for.
Compilez et exécutez le programme pour voir les résultats :
gcc main.c -o main
./main
Vous devriez voir la sortie suivante :
Array Traversal using Pointers
Forward traversal using pointer increment:
10 20 30 40 50
Backward traversal using pointer decrement:
50 40 30 20 10
Alternative backward traversal approach:
50 40 30 20 10
Cela démontre comment parcourir un tableau dans les deux sens, avant et arrière, en utilisant l'arithmétique des pointeurs. La capacité d'incrémenter et de décrémenter les pointeurs facilite le déplacement dans les tableaux dans n'importe quelle direction.
Résumé
Dans ce laboratoire, vous avez appris à parcourir des tableaux à l'aide de pointeurs en programmation C. Voici les concepts clés que nous avons abordés :
Bases des tableaux et des pointeurs :
- Les tableaux en C stockent les éléments dans des emplacements mémoire contigus.
- Les pointeurs stockent des adresses mémoire et peuvent être utilisés pour accéder à ces emplacements.
Relation entre pointeurs et tableaux :
- Le nom du tableau (sans indice) représente l'adresse du premier élément.
- Nous pouvons assigner cette adresse à un pointeur pour établir une connexion avec le tableau.
Techniques de traversée en avant :
- En utilisant l'arithmétique des pointeurs :
*(ptr + i) - En utilisant l'incrémentation de pointeur :
*ptrsuivi deptr++ - En combinant la déréférencement et l'incrémentation :
*ptr++
- En utilisant l'arithmétique des pointeurs :
Techniques de traversée en arrière :
- Initialiser le pointeur sur le dernier élément :
ptr = &arr[size-1] - Utiliser la décrémentation de pointeur :
ptr--pour se déplacer en arrière - La condition de boucle peut vérifier quand le pointeur atteint le début du tableau.
- Initialiser le pointeur sur le dernier élément :
L'arithmétique des pointeurs est une fonctionnalité puissante en C qui permet une manipulation efficace de la mémoire et offre une grande flexibilité lors de la manipulation de tableaux et d'autres structures de données. Cette technique constitue la base pour des concepts de programmation plus avancés tels que l'allocation dynamique de mémoire, les listes chaînées et d'autres structures de données complexes.



