Pointeurs et Tableaux - L'Arithmétique des Pointeurs en C

@joekakone

Joseph Konka @joekakone

03/03/2026 · 8 min

Comprenez la relation intime entre tableaux et pointeurs en C : équivalence tab[i] == *(tab + i), arithmétique des pointeurs, parcours de mémoire et const.

En langage C, les tableaux et les pointeurs sont intimement liés. En réalité, un tableau n'est rien d'autre qu'un pointeur constant vers son tout premier élément !

Comprendre cette équivalence fondamentale débloque une vision limpide de la manière dont le compilateur C manipule la mémoire vive et permet d'exploiter la technique ultra-rapide de l'arithmétique des pointeurs.


1. L'équivalence fondamentale : tab[i] == *(tab + i)#

Considérons un tableau d'entiers :

int tab[5] = {10, 20, 30, 40, 50};

En C : - Le symbole tab seul représente l'adresse mémoire du premier élément : tab == &tab[0]. - L'expression tab + 1 désigne l'adresse de la deuxième case : &tab[1]. - Déréférencer cette adresse *(tab + 1) extrait directement la valeur de la case : tab[1] (soit 20).

\[\mathbf{tab[i] \quad \Longleftrightarrow \quad *(tab + i)}\]

La notation avec les crochets tab[i] n'est en fait qu'un sucre syntaxique agréable inventé par Dennis Ritchie pour simplifier l'écriture de l'arithmétique de pointeurs *(tab + i) !


2. L'Arithmétique des pointeurs (Pointer Arithmetic)#

L'arithmétique sur les pointeurs ne fonctionne pas comme une addition mathématique ordinaire d'octets.

Lorsque vous ajoutez 1 à un pointeur, le processeur n'avance pas de 1 octet physique, mais d'un pas égal à la taille du type pointé (sizeof(*ptr)) :

  • Pour un char * (taille 1 octet) : ptr + 1 avance de 1 octet.
  • Pour un int * (taille 4 octets) : ptr + 1 avance de 4 octets.
  • Pour un double * (taille 8 octets) : ptr + 1 avance de 8 octets.
flowchart LR
    subgraph Memoire [Mémoire RAM pour int *ptr]
        C0["Adresse 0x1000\nptr (Case 0)"] -->|+ 4 octets| C1["Adresse 0x1004\nptr + 1 (Case 1)"]
        C1 -->|+ 4 octets| C2["Adresse 0x1008\nptr + 2 (Case 2)"]
    end
demonstration_arithmetique.c
#include <stdio.h>

int main(void)
{
    int entiers[3] = {100, 200, 300};
    int *p = entiers; // Équivaut à p = &entiers[0]

    printf("Adresse p     : %p | Valeur pointee : %d\n", (void*)p, *p);
    printf("Adresse p + 1 : %p | Valeur pointee : %d\n", (void*)(p + 1), *(p + 1));
    printf("Adresse p + 2 : %p | Valeur pointee : %d\n", (void*)(p + 2), *(p + 2));

    return 0;
}

3. Parcourir un tableau avec un pointeur mobile#

Les développeurs C chevronnés parcourent souvent les tableaux en faisant glisser un pointeur d'une case à l'autre avec l'opérateur d'incrémentation ptr++ :

parcours_pointeur.c
#include <stdio.h>

#define TAILLE 5

int main(void)
{
    int notes[TAILLE] = {14, 18, 12, 16, 9};
    int *curseur = notes; // Pointeur positionné au début du tableau

    printf("Parcours du tableau avec pointeur mobile :\n");
    for (int i = 0; i < TAILLE; i++)
    {
        printf("Element %d : %d (a l'adresse %p)\n", i, *curseur, (void*)curseur);
        curseur++; // Avance d'exactement sizeof(int) = 4 octets vers la case suivante
    }

    return 0;
}

4. Soustraction de pointeurs et ptrdiff_t#

Il est possible de soustraire deux pointeurs pointant dans le même tableau : le résultat n'est pas un nombre d'octets, mais le nombre exact d'éléments qui les séparent :

int tab[10];
int *debut = &tab[2];
int *fin = &tab[7];

printf("Nombre d'elements entre fin et debut : %td\n", fin - debut); // Affiche 5 !

5. Les pointeurs et le qualificateur const#

Pour sécuriser votre code et empêcher des écritures accidentelles, le C permet de verrouiller un pointeur avec const selon trois configurations :

1. Pointeur vers une donnée constante (const int *ptr)#

La valeur pointée est en lecture seule (impossible de faire *ptr = 10), mais le pointeur peut changer d'adresse :

int x = 5, y = 10;
const int *ptr = &x;
// *ptr = 20; // ERREUR : La cible est constante
ptr = &y;     // VALIDE : Le pointeur peut pointer vers une autre case

2. Pointeur constant vers une donnée variable (int * const ptr)#

L'adresse est figée (impossible de faire ptr = &y), mais la valeur pointée peut être modifiée :

int a = 5, b = 10;
int * const ptr = &a;
*ptr = 20;    // VALIDE : On modifie la valeur de 'a'
// ptr = &b;  // ERREUR : L'adresse du pointeur est verrouillée


Vous comprenez à présent comment naviguer en mémoire avec l'arithmétique des pointeurs. Découvrons dans le chapitre suivant le summum de la flexibilité en C : la gestion de la mémoire dynamique avec malloc et free.

Commentaires

Inscrivez-vous à une formation complète

Voir le catalogue