Pointeurs et tableaux
En C, il existe une relation fondamentale entre les pointeurs et les tableaux : le nom d'un tableau est un pointeur constant vers son premier élément. Cette équivalence permet de parcourir et manipuler les tableaux via l'arithmétique des pointeurs.
Tab est équivalent à &Tab[0].Pour un tableau int Tab[4] = {3, 2, 7, 9} déclaré à l'adresse 2000 (2 octets par int) :

| Expression | Signification | Valeur (exemple) |
|---|---|---|
Tab | Adresse de base (= &Tab[0]) | 2000 |
Tab + i | Adresse de Tab[i] | 2000 + i × sizeof(int) |
*(Tab + i) | Valeur de Tab[i] | Tab[i] |
&Tab[0] | Adresse du premier élément | 2000 |
Tab[i] /* notation tableau */
*(Tab + i) /* notation pointeur — identique */Le compilateur traduit Tab[i] en *(Tab + i) en interne.1. Pointeur vers un tableau 1D
int Tab[N];
int *p;
p = Tab; /* p pointe vers Tab[0] — équivalent à p = &Tab[0] */
*(p + i) /* accès à Tab[i] via le pointeur p */
*(Tab + i) /* accès à Tab[i] via le nom du tableau */Exemple n°1 — Parcours par incrémentation de pointeur
#include <stdio.h>
int main(void)
{
int Tab[4] = {3, 2, 7, 9};
int *p = Tab; /* p pointe vers Tab[0] */
int i;
for (i = 0; i < 4; i++) {
printf("Tab[%d] = %d\n", i, *p);
p++; /* avance vers l'élément suivant */
}
return 0;
}Tab[0] = 3 Tab[1] = 2 Tab[2] = 7 Tab[3] = 9
Exemple n°2 — Parcours par arithmétique d'indice (sans modifier p)
#include <stdio.h>
int main(void)
{
int Tab[4] = {3, 2, 7, 9};
int i;
for (i = 0; i < 4; i++) {
printf("Tab[%d] : adresse = %p | valeur = %d\n",
i, (void *)(Tab + i), *(Tab + i));
}
return 0;
}Tab[0] : adresse = 0x7ffd1000 | valeur = 3 Tab[1] : adresse = 0x7ffd1004 | valeur = 2 Tab[2] : adresse = 0x7ffd1008 | valeur = 7 Tab[3] : adresse = 0x7ffd100c | valeur = 9
Tab) est un pointeur constant— son adresse ne peut pas être modifiée. Pour parcourir par incrémentation, il faut utiliser une copie dans un pointeur variable :Tab++; /* ERREUR — impossible de modifier Tab */
int *p = Tab;
p++; /* correct — p est une variable */2. Pointeur vers un tableau 2D
Pour un tableau 2D Tab[L][C], les éléments sont stockés en mémoire de manière contiguë ligne par ligne (row-major order). L'élément Tab[i][j] se trouve à l'offset i × C + j depuis le début du tableau.
/* Méthode 1 — pointeur simple avec calcul d'offset */
int *p = (int *)Tab;
*(p + i * nb_colonnes + j) /* équivalent à Tab[i][j] */
/* Méthode 2 — double déréférencement */
*(*(Tab + i) + j) /* équivalent à Tab[i][j] */| Notation | Signification | Équivalent tableau |
|---|---|---|
Tab + i | Adresse de la ligne i | &Tab[i] |
*(Tab + i) | Pointeur vers le 1er élément de la ligne i | Tab[i] |
*(Tab + i) + j | Adresse de l'élément [i][j] | &Tab[i][j] |
*(*(Tab + i) + j) | Valeur de l'élément [i][j] | Tab[i][j] |
Exemple n°3 — Parcours d'un tableau 2D (méthode 1 — offset)
#include <stdio.h>
int main(void)
{
int Tab[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int *p = (int *)Tab; /* pointeur simple vers le début du tableau */
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
printf("Tab[%d][%d] = %2d\n", i, j, *(p + i * 4 + j));
}
}
return 0;
}Tab[0][0] = 1 Tab[0][1] = 2 Tab[0][2] = 3 Tab[0][3] = 4 Tab[1][0] = 5 Tab[1][1] = 6 Tab[1][2] = 7 Tab[1][3] = 8 Tab[2][0] = 9 Tab[2][1] = 10 Tab[2][2] = 11 Tab[2][3] = 12
Exemple n°4 — Parcours d'un tableau 2D (méthode 2 — double déréférencement)
#include <stdio.h>
int main(void)
{
int Tab[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
int i, j;
for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
printf("Tab[%d][%d] = %2d\n", i, j, *(*(Tab + i) + j));
}
}
return 0;
}| Méthode | Expression | Note |
|---|---|---|
| Tableau standard | Tab[i][j] | La plus lisible |
| Pointeur + offset | *(p + i * C + j) | p = (int *)Tab |
| Double déréférencement | *(*(Tab + i) + j) | Sans pointeur auxiliaire |
3. Tableau de pointeurs
type *nom_tab[taille]; /* tableau de pointeurs vers type */
int *Tab[5]; /* 5 pointeurs vers int */
char *noms[4]; /* 4 pointeurs vers char (4 chaînes) */Exemple n°5 — Tableau de pointeurs vers des entiers
#include <stdio.h>
int main(void)
{
int a = 3, b = 7, c = 1;
int *Tab[3];
Tab[0] = &a;
Tab[1] = &b;
Tab[2] = &c;
for (int i = 0; i < 3; i++) {
printf("Tab[%d] : adresse = %p | valeur = %d\n",
i, (void *)Tab[i], *Tab[i]);
}
return 0;
}Tab[0] : adresse = 0x7ffd1010 | valeur = 3 Tab[1] : adresse = 0x7ffd1014 | valeur = 7 Tab[2] : adresse = 0x7ffd1018 | valeur = 1
Exemple n°6 — Tableau de chaînes de caractères
#include <stdio.h>
int main(void)
{
char *noms[4] = {
"ESSADDOUKI Mostafa",
"KAYOUH Mohamed",
"ESSADDOUKI Ismail",
"SEKHRA Omar"
};
for (int i = 0; i < 4; i++) {
printf("noms[%d] = %s\n", i, noms[i]);
}
return 0;
}noms[0] = ESSADDOUKI Mostafa noms[1] = KAYOUH Mohamed noms[2] = ESSADDOUKI Ismail noms[3] = SEKHRA Omar
char *noms[N] est plus flexible qu'un tableau char noms[N][L] : chaque chaîne peut avoir une longueur différente sans gaspillage mémoire. En revanche, les pointeurs pointent vers des chaînes littérales en mémoire lecture seule — pour des chaînes modifiables, utiliser char noms[N][L] ou allouer dynamiquement.Exemple n°7 — Tableau 2D dynamique via tableau de pointeurs
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int L = 3, C = 4;
int i, j;
int *Tab[3];
/* Allocation d'une ligne de 4 entiers pour chaque pointeur */
for (i = 0; i < L; i++) {
Tab[i] = (int *)malloc(C * sizeof(int));
if (Tab[i] == NULL) { perror("malloc"); exit(1); }
}
/* Remplissage : Tab[i][j] = i * j */
for (i = 0; i < L; i++)
for (j = 0; j < C; j++)
*(*(Tab + i) + j) = i * j;
/* Affichage */
for (i = 0; i < L; i++) {
for (j = 0; j < C; j++)
printf("Tab[%d][%d] = %2d\n", i, j, *(*(Tab + i) + j));
}
/* Libération */
for (i = 0; i < L; i++) free(Tab[i]);
return 0;
}Tab[0][0] = 0 Tab[0][1] = 0 Tab[0][2] = 0 Tab[0][3] = 0 Tab[1][0] = 0 Tab[1][1] = 1 Tab[1][2] = 2 Tab[1][3] = 3 Tab[2][0] = 0 Tab[2][1] = 2 Tab[2][2] = 4 Tab[2][3] = 6
| Approche | Déclaration | Mémoire contiguë | Taille des lignes | Modifiable |
|---|---|---|---|---|
| Tableau 2D statique | int Tab[L][C] | Oui | Fixe | Oui |
| Tableau de pointeurs | int *Tab[L] | Non (lignes indépendantes) | Variable | Oui |
| Tableau de chaînes (littérales) | char *Tab[N] | Non | Variable | Non (lecture seule) |
Récapitulatif
| Expression | Signification | Équivalent |
|---|---|---|
Tab | Adresse du 1er élément | &Tab[0] |
*(Tab + i) | Valeur de l'élément i | Tab[i] |
*(p + i * C + j) | Élément [i][j] d'un tableau 2D | Tab[i][j] |
*(*(Tab + i) + j) | Élément [i][j] par double déréférencement | Tab[i][j] |
int *Tab[N] | Tableau de N pointeurs vers int | — |
char *Tab[N] | Tableau de N chaînes | — |
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.