Langage C/C++

L’Arithmétique des Pointeurs en Langage C

L’arithmétique des pointeurs est une fonctionnalité puissante en langage C qui permet de manipuler les adresses mémoire et de naviguer dans des structures de données comme les tableaux en utilisant des pointeurs. Elle repose sur le fait que les pointeurs stockent des adresses, et que ces adresses sont manipulables à l’aide d’opérateurs arithmétiques.

1. Notions de Base

En C, un pointeur ne représente pas seulement une adresse mémoire, il est aussi associé à un type de données (par exemple int*, char*, etc.). Cela permet au compilateur de savoir combien d’octets doivent être “sautés” lors des opérations arithmétiques sur ce pointeur. Voici les principales opérations d’arithmétique des pointeurs :

  • Incrémentation (++)
  • Décrémentation (--)
  • Addition (+)
  • Soustraction (-)

Ces opérations sont couramment utilisées pour parcourir des tableaux ou manipuler des données en mémoire.

2. Incrémentation d’un pointeur (++)

Lorsque vous incrémentez un pointeur, il ne s’incrémente pas d’un octet mais du nombre d’octets correspondant au type de données vers lequel il pointe.

Exemple :

#include <stdio.h>

int main() {
    int tableau[3] = {10, 20, 30};
    int *p = tableau;  // p pointe vers le premier élément du tableau

    printf("Valeur initiale pointée par p : %d\n", *p);  // Affiche 10

    p++;  // Incrémentation du pointeur (il "saute" à l'adresse du prochain entier)
    printf("Valeur après incrémentation : %d\n", *p);  // Affiche 20

    return 0;
}

Explication :

  • p++ incrémente le pointeur p pour qu’il pointe vers l’élément suivant du tableau.
  • Comme p est un pointeur vers un int, et que chaque int fait généralement 4 octets, le pointeur “saute” de 4 octets pour pointer vers l’élément suivant.

3. Décrémentation d’un pointeur (--)

Similaire à l’incrémentation, mais dans le sens inverse : le pointeur est décrémenté pour pointer vers l’élément précédent.

Exemple :

#include <stdio.h>

int main() {
    int tableau[3] = {10, 20, 30};
    int *p = &tableau[2];  // p pointe vers le dernier élément

    printf("Valeur initiale pointée par p : %d\n", *p);  // Affiche 30

    p--;  // Décrémentation du pointeur
    printf("Valeur après décrémentation : %d\n", *p);  // Affiche 20

    return 0;
}

Explication :

  • p-- fait en sorte que le pointeur p recule vers l’adresse de l’élément précédent dans le tableau.

4. Addition et soustraction de pointeurs (+, -)

En plus des incrémentations et décrémentations unitaires, vous pouvez ajouter ou soustraire des entiers à un pointeur. Cela est utile pour parcourir un tableau ou manipuler des blocs de mémoire.

Exemple : Addition de pointeurs

#include <stdio.h>

int main() {
    int tableau[5] = {10, 20, 30, 40, 50};
    int *p = tableau;  // p pointe vers le premier élément du tableau

    printf("Valeur de tableau[3] via arithmétique des pointeurs : %d\n", *(p + 3));  // Affiche 40

    return 0;
}

Explication :

  • *(p + 3) signifie “l’adresse pointée par p, plus trois entiers”, ce qui correspond à tableau[3]. Le pointeur avance de 3 fois la taille d’un int (généralement 4 octets).

Exemple : Soustraction de pointeurs

#include <stdio.h>

int main() {
    int tableau[5] = {10, 20, 30, 40, 50};
    int *p = &tableau[4];  // p pointe vers le dernier élément du tableau

    printf("Valeur après soustraction de 2 : %d\n", *(p - 2));  // Affiche 30

    return 0;
}

Explication :

  • *(p - 2) déplace le pointeur p deux éléments en arrière, ce qui correspond à tableau[2] (valeur 30).

5. Différence entre deux pointeurs

Lorsque deux pointeurs pointent vers des éléments du même tableau, il est possible de calculer la distance entre eux en utilisant la soustraction. Le résultat est le nombre d’éléments qui séparent les deux pointeurs.

Exemple :

#include <stdio.h>

int main() {
    int tableau[5] = {10, 20, 30, 40, 50};
    int *p1 = &tableau[1];  // Pointeur sur tableau[1]
    int *p2 = &tableau[4];  // Pointeur sur tableau[4]

    printf("Distance entre p1 et p2 : %ld\n", p2 - p1);  // Affiche 3

    return 0;
}

Explication :

  • p2 - p1 calcule le nombre d’éléments entre tableau[1] et tableau[4], ce qui donne 3.

6. Cas des pointeurs de types différents

L’arithmétique des pointeurs dépend du type de données auquel le pointeur fait référence, car chaque type a une taille en mémoire différente. Par exemple, un pointeur vers un char (1 octet) incrémente de 1 octet, tandis qu’un pointeur vers un int (4 octets) incrémente de 4 octets.

Exemple avec différents types :

#include <stdio.h>

int main() {
    char c = 'A';
    int i = 100;

    char *p_char = &c;
    int *p_int = &i;

    printf("Adresse de c : %p, après incrémentation de p_char : %p\n", p_char, p_char + 1);
    printf("Adresse de i : %p, après incrémentation de p_int : %p\n", p_int, p_int + 1);

    return 0;
}

Explication :

  • p_char + 1 incrémente l’adresse de 1 octet (car char est sur 1 octet).
  • p_int + 1 incrémente l’adresse de 4 octets (car int est généralement sur 4 octets).

7. Arithmétique interdite sur les pointeurs

Certaines opérations arithmétiques ne sont pas autorisées avec les pointeurs, car elles n’ont pas de sens en termes d’adresses mémoire :

  • Multiplication (*) et division (/) : Vous ne pouvez pas multiplier ou diviser des pointeurs.
  • Addition de deux pointeurs : Vous ne pouvez pas additionner deux pointeurs entre eux.

👉 L’arithmétique des pointeurs permet de manipuler efficacement des structures de données comme les tableaux, en déplaçant les pointeurs pour accéder aux différents éléments. Les opérations les plus courantes incluent l’incrémentation, la décrémentation, l’addition et la soustraction, mais il est important de toujours comprendre ce que vous faites, car une mauvaise manipulation des pointeurs peut entraîner des erreurs graves telles que des dépassements de mémoire ou des accès invalides.

Voici quelques exercices corrigés sur l’arithmétique des pointeurs en C, avec des explications détaillées pour vous aider à comprendre chaque étape.


Exercice 1 : Accéder aux éléments d’un tableau avec un pointeur

Énoncé :

Écrivez un programme qui utilise un pointeur pour accéder et afficher les éléments d’un tableau d’entiers.

Solution :

#include <stdio.h>

int main() {
    int tableau[5] = {1, 2, 3, 4, 5};
    int *p = tableau;  // Pointeur vers le premier élément du tableau

    for (int i = 0; i < 5; i++) {
        printf("Élément %d : %d\n", i, *(p + i));  // Accès via l'arithmétique des pointeurs
    }

    return 0;
}

Explication :

  • Le pointeur p pointe vers le premier élément du tableau (tableau[0]).
  • *(p + i) permet d’accéder à chaque élément du tableau en utilisant l’arithmétique des pointeurs.
  • Le programme parcourt les éléments du tableau et les affiche.

Exercice 2 : Incrémentation d’un pointeur

Énoncé :

Modifiez l’exercice précédent pour afficher les éléments du tableau en incrémentant le pointeur à chaque itération de la boucle.

Solution :

#include <stdio.h>

int main() {
    int tableau[5] = {10, 20, 30, 40, 50};
    int *p = tableau;  // Pointeur vers le premier élément du tableau

    for (int i = 0; i < 5; i++) {
        printf("Élément %d : %d\n", i, *p);  // Affiche la valeur pointée par p
        p++;  // Incrémentation du pointeur pour pointer vers l'élément suivant
    }

    return 0;
}

Explication :

  • p++ incrémente le pointeur pour passer à l’élément suivant dans le tableau.
  • Le programme affiche successivement les valeurs des éléments du tableau sans avoir besoin d’utiliser d’indices.

Exercice 3 : Soustraction de deux pointeurs

Énoncé :

Écrivez un programme qui calcule la distance entre deux pointeurs dans un tableau.

Solution :

#include <stdio.h>

int main() {
    int tableau[6] = {5, 10, 15, 20, 25, 30};
    int *p1 = &tableau[1];  // Pointeur vers le deuxième élément
    int *p2 = &tableau[4];  // Pointeur vers le cinquième élément

    // Calcul de la distance entre les deux pointeurs
    int distance = p2 - p1;

    printf("Distance entre p1 et p2 : %d éléments\n", distance);

    return 0;
}

Explication :

  • p2 - p1 calcule la distance entre les deux pointeurs en termes d’éléments du tableau.
  • Le résultat de la soustraction est le nombre d’éléments qui séparent les deux pointeurs dans le tableau, ici 3 (car tableau[4] - tableau[1] = 3).

Exercice 4 : Échanger deux valeurs d’un tableau avec des pointeurs

Énoncé :

Écrivez une fonction qui prend deux pointeurs vers des éléments d’un tableau et échange leurs valeurs.

Solution :

#include <stdio.h>

void echanger(int *p1, int *p2) {
    int temp = *p1;  // Sauvegarde de la valeur pointée par p1
    *p1 = *p2;       // p1 prend la valeur pointée par p2
    *p2 = temp;      // p2 prend la valeur temporaire (ancienne valeur de p1)
}

int main() {
    int tableau[5] = {10, 20, 30, 40, 50};

    // Affichage du tableau avant l'échange
    printf("Avant l'échange : %d, %d\n", tableau[1], tableau[3]);

    // Appel de la fonction pour échanger tableau[1] et tableau[3]
    echanger(&tableau[1], &tableau[3]);

    // Affichage du tableau après l'échange
    printf("Après l'échange : %d, %d\n", tableau[1], tableau[3]);

    return 0;
}

Explication :

  • La fonction echanger() prend deux pointeurs en argument, qui pointent vers les deux éléments à échanger.
  • Les valeurs pointées par p1 et p2 sont échangées à l’aide d’une variable temporaire.
  • Le programme échange les éléments tableau[1] (valeur 20) et tableau[3] (valeur 40).

Exercice 5 : Inverser un tableau à l’aide de l’arithmétique des pointeurs

Énoncé :

Écrivez un programme qui utilise des pointeurs pour inverser les éléments d’un tableau.

Solution :

#include <stdio.h>

void inverser_tableau(int *arr, int taille) {
    int *debut = arr;             // Pointeur vers le début du tableau
    int *fin = arr + taille - 1;  // Pointeur vers la fin du tableau
    int temp;

    // Inversion des éléments en utilisant des pointeurs
    while (debut < fin) {
        temp = *debut;
        *debut = *fin;
        *fin = temp;

        debut++;  // Avancer le pointeur vers le début
        fin--;    // Reculer le pointeur vers la fin
    }
}

int main() {
    int tableau[6] = {1, 2, 3, 4, 5, 6};

    // Affichage avant inversion
    printf("Avant inversion : ");
    for (int i = 0; i < 6; i++) {
        printf("%d ", tableau[i]);
    }
    printf("\n");

    // Inversion du tableau
    inverser_tableau(tableau, 6);

    // Affichage après inversion
    printf("Après inversion : ");
    for (int i = 0; i < 6; i++) {
        printf("%d ", tableau[i]);
    }
    printf("\n");

    return 0;
}

Explication :

  • La fonction inverser_tableau() utilise deux pointeurs : debut pour parcourir le tableau depuis le début et fin depuis la fin.
  • Les éléments sont échangés jusqu’à ce que les deux pointeurs se rencontrent au milieu du tableau.
  • Le programme affiche le tableau avant et après l’inversion.

Exercice 6 : Trouver la plus grande valeur d’un tableau avec des pointeurs

Énoncé :

Écrivez une fonction qui trouve et retourne la plus grande valeur d’un tableau d’entiers en utilisant des pointeurs.

Solution :

#include <stdio.h>

int trouver_max(int *arr, int taille) {
    int *p = arr;
    int max = *p;  // Initialiser le max avec le premier élément

    // Parcourir le tableau
    for (int i = 1; i < taille; i++) {
        p++;  // Avancer le pointeur
        if (*p > max) {
            max = *p;  // Mettre à jour le maximum
        }
    }

    return max;
}

int main() {
    int tableau[5] = {15, 30, 25, 40, 10};

    int max = trouver_max(tableau, 5);

    printf("La plus grande valeur du tableau est : %d\n", max);

    return 0;
}

Explication :

  • La fonction trouver_max() parcourt le tableau en utilisant un pointeur p, en le déplaçant à chaque itération avec p++.
  • Le programme compare chaque valeur du tableau avec le max actuel et met à jour le max si une valeur plus grande est trouvée.

Conclusion

Ces exercices couvrent différentes applications de l’arithmétique des pointeurs en C, depuis l’accès aux éléments de tableaux jusqu’à la manipulation plus complexe de structures de données. En pratiquant ces exemples, vous apprendrez à utiliser les pointeurs pour parcourir et modifier des données en mémoire de manière efficace.

Autres articles

Guide : Comment créer un QCM en...
Le QCM en langage C peut être simulé dans un...
Read more
Tableaux en Langage C : Exercices Corrigés
Voici une série d'exercices corrigés sur les tableaux en langage...
Read more
Comment fonctionne la récursion terminale en C...
La récursion terminale en CLa récursion terminale est une forme...
Read more

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *