Les pointeurs en langage C
Un pointeur est une variable spéciale qui stocke l'adresse mémoire d'une autre variable. Chaque pointeur est lié à un type de données précis : un pointeur sur int ne peut pointer que vers un entier, un pointeur sur float vers un flottant, etc.
&— opérateur d'adresse : retourne l'adresse d'une variable*— opérateur de déréférencement : accède à la valeur stockée à une adresse
1. Les deux opérateurs fondamentaux
| Opérateur | Nom | Rôle | Exemple |
|---|---|---|---|
& | Adresse de | Retourne l'adresse mémoire d'une variable | &x → adresse de x |
* (déclaration) | Pointeur | Déclare une variable de type pointeur | int *ptr |
* (usage) | Déréférencement | Accède à la valeur pointée | *ptr → valeur à l'adresse |
Exemple n°1 — Afficher l'adresse d'une variable
#include <stdio.h>
int main(void)
{
int x;
printf("adresse de x est : %p\n", &x);
return 0;
}adresse de x est : 0x7ffee6ffea28
%p Le format %p de printf est dédié à l'affichage des adresses mémoire en hexadécimal. La valeur exacte dépend du système et varie à chaque exécution.Exemple n°2 — Déclarer un pointeur et lui affecter une adresse
#include <stdio.h>
int main(void)
{
int x = 10;
/* int *ptr : ptr est un pointeur vers un entier */
int *ptr;
/* ptr reçoit l'adresse de x */
ptr = &x;
printf("x = %d\n", x);
printf("&x = %p\n", &x);
printf("ptr = %p\n", ptr); // même adresse que &x
printf("*ptr = %d\n", *ptr); // valeur à cette adresse = 10
return 0;
}x = 10 &x = 0x7ffee6ffea28 ptr = 0x7ffee6ffea28 *ptr = 10
Exemple n°3 — Modifier une variable via son pointeur
#include <stdio.h>
int main(void)
{
int x = 2;
int *ptr = &x; /* ptr pointe sur x */
*ptr = 5; /* équivaut à : x = 5 */
printf("*ptr = %d\n", *ptr);
printf("x = %d\n", x);
return 0;
}*ptr = 5 x = 5
2. Déclaration d'un pointeur
type *nom_du_pointeur;
/* Exemples */
char *buffer; /* pointeur vers un caractère */
int *px; /* pointeur vers un entier */
float *py; /* pointeur vers un flottant */int *p;
*p = 5; /* comportement indéfini — p pointe nulle part */
/* Correct : initialiser d'abord */
int x;
int *p = &x;
*p = 5; /* valide */3. Initialisation d'un pointeur
Un pointeur doit pointer vers une zone mémoire réservée par le compilateur. Il existe deux façons valides d'initialiser un pointeur.
| Méthode | Description | Libération requise |
|---|---|---|
| Adresse d'une variable | p = &variable; | Non — gérée automatiquement |
| Allocation dynamique | p = (int*)malloc(sizeof(int)); | Oui — appeler free(p) |
| Pointeur nul | p = 0; ou p = NULL; | Non — indique "ne pointe nulle part" |
Exemple n°4 — Initialisation statique et dynamique
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int f;
int *pf, *pg;
/* Initialisation statique — pointe vers une variable existante */
pf = &f;
*pf = 42;
printf("*pf = %d\n", *pf);
/* Initialisation dynamique — allocation d'un entier en mémoire */
pg = (int*)malloc(sizeof(int));
*pg = 100;
printf("*pg = %d\n", *pg);
/* Libération de la mémoire allouée dynamiquement */
free(pg);
/* Pointeur nul — indique qu'il ne pointe nulle part */
pg = 0; /* ou NULL */
return 0;
}*pf = 42 *pg = 100
4. Utilisation des pointeurs
Une fois déclaré et initialisé, on accède au contenu de l'adresse pointée via l'opérateur *. Il est important de distinguer *P et &P :
| Expression | Signification | Exemple avec P = &A |
|---|---|---|
P | L'adresse stockée dans P | Adresse de A |
*P | La valeur à l'adresse pointée | Valeur de A |
&P | L'adresse du pointeur lui-même | Adresse de la variable P |
Exemple n°5 — Opérations via pointeur
int *P;
int A = 10;
P = &A; /* P pointe sur A */
*P = *P + 1; /* équivaut à : A = A + 1 → A = 11 */
*P = 5; /* équivaut à : A = 5 */
5. Opérations élémentaires sur les pointeurs
Priorité des opérateurs
Les opérateurs * et & ont la même priorité que les autres opérateurs unaires (!, ++, --). Dans une même expression, les opérateurs unaires sont évalués de droite à gauche.
Arithmétique de pointeur
Un ensemble limité d'opérations arithmétiques peut être effectué sur des pointeurs :
| Opération | Syntaxe | Signification |
|---|---|---|
| Incrémenter | P++ | P pointe sur l'élément suivant |
| Décrémenter | P-- | P pointe sur l'élément précédent |
| Ajouter un entier | P + n ou P += n | P pointe n éléments plus loin |
| Soustraire un entier | P - n ou P -= n | P pointe n éléments en arrière |
| Soustraire deux pointeurs | P2 - P1 | Nombre d'éléments entre P1 et P2 |
Exemple n°6 — Opérations arithmétiques sur pointeur
int x, y;
int *P;
P = &x;
y = *P + 1; /* y = x + 1 (lit la valeur pointée) */
*P = *P + 10; /* x = x + 10 (modifie via pointeur) */
*P += 2; /* x += 2 */
(*P)++; /* x++ — parenthèses OBLIGATOIRES */(*P)++ vs *P++ Les parenthèses sont indispensables pour incrémenter la valeur pointée. Sans elles, c'est le pointeurlui-même qui est incrémenté :(*P)++ /* incrémente la valeur à l'adresse — correct */
*P++ /* incrémente le pointeur P — comportement inattendu */Exemple n°7 — Copier un pointeur (deux pointeurs sur la même variable)
#include <stdio.h>
int main(void)
{
int x = 5;
int *p1, *p2;
p2 = &x;
p1 = p2; /* p1 et p2 pointent maintenant sur x */
printf("*p1 = %d\n", *p1);
printf("*p2 = %d\n", *p2);
/* Modifier via p1 change aussi ce que voit p2 */
*p1 = 99;
printf("après *p1=99 : *p2 = %d\n", *p2);
return 0;
}*p1 = 5 *p2 = 5 après *p1=99 : *p2 = 99
0 (ou NULL) est la seule valeur numérique qu'on peut affecter directement à un pointeur. Elle signifie que le pointeur ne pointe nulle partet sert à indiquer l'absence de valeur valide :int *P = 0; /* ou NULL — pointeur nul */
if (P != NULL) /* toujours vérifier avant déréférencement */
*P = 5;6. Pointeurs et tableaux
a. Tableau à une dimension
A, A équivaut à &A[0]. La différence essentielle avec un pointeur ordinaire est que le nom d'un tableau ne peut pas être modifié (constante).| Expression | Équivalent | Description |
|---|---|---|
A | &A[0] | Adresse du 1er élément |
A+i | &A[i] | Adresse du i-ème élément |
*(A+i) | A[i] | Valeur du i-ème élément |
P = A | P = &A[0] | P pointe sur le début du tableau |
*(P+i) | A[i] | Accès au i-ème élément via pointeur |

| Opération | Pointeur P | Nom de tableau A |
|---|---|---|
P = A | Permis | Non permis (A = P interdit) |
P++ | Permis | Non permis (A++ interdit) |
*(P+i) | Permis | Permis (*(A+i)) |
Exemple n°8 — Initialiser un tableau à 1 — trois versions
/* Version 1 — sans pointeur */
int main(void)
{
int Tab[10], i;
for (i = 0; i < 10; i++)
Tab[i] = 1;
return 0;
}
/* Version 2 — avec pointeur et indice */
int main(void)
{
int Tab[10], i;
int *P = Tab;
for (i = 0; i < 10; i++)
*(P + i) = 1;
return 0;
}
/* Version 3 — avec pointeur incrémenté */
int main(void)
{
int Tab[10];
int *P;
for (P = Tab; P < (Tab + 10); P++)
*P = 1;
return 0;
}P parcourt directement les cases du tableau sans variable d'indice. La condition P < Tab + 10 exploite l'arithmétique de pointeur pour détecter la fin.b. Tableau à deux dimensions
Tab[i][j] est équivalent à *(*(Tab + i) + j).![Schéma — tableau 2D TAB[6][7] en mémoire](/upload/5f906bccee6a9b5e9f50409fe8645093ee49c0ba.jpeg)
Exemple n°9 — Accès aux éléments d'un tableau 2D via pointeurs
int Tab[3][4] = {{ 0, 1, 2, 3},
{10, 11, 12, 13},
{20, 21, 22, 23}};
/* Tab → adresse de Tab[0] = {0,1,2,3} */
/* Tab + 1 → adresse de Tab[1] = {10,11,12,13} */
/* Tab[i][j] = *(*(Tab + i) + j) */
Exemple n°10 — Initialiser un tableau 2D à 1 — trois versions
/* Version 1 — sans pointeur */
int main(void)
{
int Tab[5][4], i, j;
for (i = 0; i < 5; i++)
for (j = 0; j < 4; j++)
Tab[i][j] = 1;
return 0;
}
/* Version 2 — tableau de pointeurs *P[5] */
int main(void)
{
int Tab[5][4];
int *P[5]; /* tableau de 5 pointeurs — un par ligne */
int i, j;
/* Chaque P[i] pointe sur le début de la ligne i */
for (i = 0; i < 5; i++)
P[i] = Tab[i];
for (i = 0; i < 5; i++)
for (j = 0; j < 4; j++)
*(*(P + i) + j) = 1; /* équivaut à P[i][j] = 1 */
return 0;
}
/* Version 3 — pointeur simple sur la mémoire linéaire */
int main(void)
{
int Tab[5][4];
int *P = Tab[0]; /* pointe sur le 1er élément */
int i;
/* Les 5*4 = 20 éléments sont adjacents en mémoire */
for (i = 0; i < 5 * 4; i++)
*(P + i) = 1;
return 0;
}Récapitulatif
| Concept | Syntaxe | Description |
|---|---|---|
| Déclaration | int *p; | p est un pointeur vers un entier |
| Initialisation | p = &x; | p reçoit l'adresse de x |
| Déréférencement | *p | Valeur à l'adresse pointée |
| Modification | *p = 5; | Modifie la variable originale |
| Incrément valeur | (*p)++ | Incrémente la valeur (parenthèses obligatoires) |
| Tableau 1D | *(p+i) = A[i] | Accès au i-ème élément |
| Tableau 2D | *(*(p+i)+j) = A[i][j] | Accès à l'élément ligne i, colonne j |
| Pointeur nul | p = NULL; | Indique l'absence de valeur valide |
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.