Cours programmation en langage C : Chapitre 6 - Les pointeurs

Ce cours porte sur les pointeurs en langage C, destiné aux étudiants de première année en informatique appliquée. Il explique les notions fondamentales d'adressage direct et indirect, la déclaration et l'utilisation des pointeurs, leur relation avec les tableaux, ainsi que l'arithmétique des pointeurs.

D'après le document Cours programmation en langage C : Chapitre 6 - Les pointeurs

Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Document source

Cours programmation en langage C : Chapitre 6 - Les pointeurs

Computer Science · PDF · 9 pages · 2011

Afficher l'aperçu du document

Consulter le document original →

Ce cours porte sur les pointeurs en langage C, destiné aux étudiants de première année en informatique appliquée. Il explique les notions fondamentales d'adressage direct et indirect, la déclaration et l'utilisation des pointeurs, leur relation avec les tableaux, ainsi que l'arithmétique des pointeurs. Ce matériel est conçu pour faciliter la compréhension et la manipulation des pointeurs dans la programmation C.

Adressage direct

En programmation, une variable stocke une information à un emplacement précis en mémoire. Le nom de la variable permet d'accéder directement à cette valeur. Cet accès s'appelle adressage direct.

Exemple :

int a = 10;
printf("%d", a);   // affiche : 10
printf("%p", &a);  // affiche l'adresse mémoire de a, par exemple : F800

Adressage indirect

Si l'on ne veut pas ou ne peut pas utiliser le nom d'une variable, on peut utiliser un pointeur, c'est-à-dire une variable spéciale qui contient l'adresse d'une autre variable. L'accès à la valeur se fait alors via ce pointeur. C'est l'adressage indirect.

Exemple :

int a = 10;
int *q;
q = &a;

printf("%d", a);    // 10
printf("%p", &a);   // adresse de a, par exemple F802H
printf("%p", q);    // même adresse que &a : F802H
printf("%p", &q);   // adresse de q, différente : F400H
printf("%d", *q);   // 10, contenu pointé par q

On dit que q pointe sur a.

Définition : Pointeur

Un pointeur est une variable spéciale qui contient l'adresse d'une autre variable. En C, chaque pointeur est lié à un type de données précis. Un pointeur sur int ne peut contenir que l'adresse d'une variable de type int ou d'un élément d'un tableau d'int.

Remarque : Le nom d'une variable est lié à une adresse fixe, tandis qu'un pointeur peut changer d'adresse pointée.

Les opérateurs de base

  • Opérateur adresse de : & — permet d'obtenir l'adresse d'une variable.
  • Opérateur contenu de : * — permet d'accéder au contenu de l'adresse pointée par un pointeur.
  • Déclaration d'un pointeur : <Type> *<NomPointeur>;

Exemple d'utilisation de & avec scanf :

int n;
printf("donner un nombre entier : ");
scanf("%d", &n);

Attention : L'opérateur & ne peut s'appliquer qu'à des variables ou tableaux, pas à des constantes ou expressions.

Opérations élémentaires sur pointeurs

Les opérateurs unaires * et & ont la même priorité que les autres opérateurs unaires et sont évalués de droite à gauche.

Si P pointe sur une variable X, alors *P peut être utilisé partout où X est utilisé.

Exemples d'équivalences après P = &X; :

  • Y = *P + 1; équivaut à Y = X + 1;
  • *P = *P + 10; équivaut à X = X + 10;
  • *P += 2; équivaut à X += 2;
  • ++*P; équivaut à ++X;
  • (*P)++; équivaut à X++; (parenthèses nécessaires)

On ne peut affecter qu'une adresse à un pointeur. Les pointeurs peuvent être affectés entre eux :

int *P1, *P2;
P1 = P2;  // P1 pointe sur le même objet que P2

Pointeurs et tableaux

En C, le nom d'un tableau représente l'adresse de son premier élément. Ainsi :

  • tab est équivalent à &tab[0]
  • tab[i] est équivalent à *(tab + i)
  • &tab[i] est équivalent à tab + i

Exemple :

int tab[5] = {11, 12, 13, 14, 15};
IndiceValeurAdresse (exemple)
011F800
112F810
213F820
314F830
415F840

On peut accéder aux éléments ainsi :

  • tab[0] ou *tab ou *(tab+0) donne 11
  • tab[1] ou *(tab+1) donne 12
  • etc.

Exemple d'utilisation d'un tableau et d'un pointeur

int tab[5] = {11, 12, 13, 14, 15};
int *q;
q = tab;  // q pointe sur tab[0]

printf("%d\n", *q);      // 11
printf("%d\n", *(q+1));  // 12
printf("%d\n", *(q+4));  // 15

Exemple avec déplacement du pointeur

q = tab + 2;  // q pointe sur tab[2]
printf("%d\n", *q);      // 13
printf("%d\n", *(q+1));  // 14
printf("%d\n", *(q-2));  // 11

Incrémentation du pointeur

q = tab;
q++;
printf("%d\n", *q);      // 12, q pointe sur tab[1]

Résumé sur pointeurs et tableaux

Pour un tableau tab de type int et un pointeur q sur int :

int tab[10];
int *q;
q = tab;  // équivalent à q = &tab[0];

Les opérations suivantes sont valides :

  • q + i pointe sur la i-ème composante après q
  • q - i pointe sur la i-ème composante avant q
  • *(q + i) donne le contenu de la i-ème composante après q

Remarque : q + i n'adresse pas le i-ième octet après q, mais la i-ème composante, en tenant compte de la taille du type pointé.

Exemple :

float tab[20], X;
float *q;
q = tab;
X = *(q + 9);  // X reçoit la valeur de tab[9]

Le compilateur calcule l'adresse en ajoutant 9 fois la taille d'un float (4 octets) à l'adresse dans q.

Attention : Le nom d'un tableau est une constante, on ne peut pas faire tab++, alors que q++ est permis.

Formalisation tableau et pointeur

Il est possible de traduire un programme utilisant la notation tableau en un programme utilisant la notation pointeur.

Exemple :

#include <stdio.h>
void main() {
    int tab[50];
    int i, n;

    printf("saisir la taille du tableau  ");
    scanf("%d", &n);
    for (i = 0; i < n; i++)
        scanf("%d", &tab[i]);

    for (i = 0; i < n; i++)
        printf("l'element d'indice %d est %d \n", i, tab[i]);
}

Version équivalente en formalisme pointeur :

#include <stdio.h>
void main() {
    int tab[50];
    int i, n;

    printf("saisir la taille du tableau  ");
    scanf("%d", &n);

    for (i = 0; i < n; i++)
        scanf("%d", tab + i);

    for (i = 0; i < n; i++)
        printf("l'element d'indice %d est %d \n", i, *(tab + i));
}

Arithmétique des pointeurs

Le langage C permet d'effectuer des opérations arithmétiques sur les pointeurs, en tenant compte du type pointé :

  • Affectation : Si P1 et P2 sont pointeurs du même type, P1 = P2; fait pointer P1 sur le même objet que P2.
  • Addition et soustraction : Si P pointe sur A[i], alors P + n pointe sur A[i + n] et P - n sur A[i - n].
  • Incrémentation et décrémentation :
    • P++ pointe sur A[i + 1]
    • P += n pointe sur A[i + n]
    • P-- pointe sur A[i - 1]
    • P -= n pointe sur A[i - n]

Domaine des opérations : Ces opérations sont définies uniquement à l'intérieur d'un tableau. Sortir du domaine du tableau produit un comportement indéfini.

Exemples

int A[10];
int *P;

P = A + 9;   // légal : dernier élément
P = A + 11;  // illégal : dépasse la taille
P = A - 1;   // illégal : avant le début

Soustraction de deux pointeurs

Si P1 et P2 pointent dans le même tableau :

  • P1 - P2 donne le nombre d'éléments entre eux.
  • Le résultat est négatif si P1 précède P2, zéro s'ils sont égaux, positif si P2 précède P1.
  • Indéfini si les pointeurs ne pointent pas dans le même tableau.

Comparaison de pointeurs

On peut comparer deux pointeurs avec <, >, <=, >=, ==, !=. Si les pointeurs pointent dans le même tableau, la comparaison correspond à celle des indices.

Exemple de programme avec pointeur pour remplir et afficher un tableau

#include <stdio.h>
void main() {
    int tab[50];
    int i, n, *q;

    printf("saisir la taille du tableau  ");
    scanf("%d", &n);

    for (q = tab; q < tab + n; q++)
        scanf("%d", q);

    for (q = tab; q < tab + n; q++)
        printf("l'element d'indice %d est %d \n", (int)(q - tab), *q);
}

Glossaire des termes clés

  • Adressage direct : Accès à la valeur d'une variable via son nom.
  • Adressage indirect : Accès à la valeur d'une variable via un pointeur contenant son adresse.
  • Pointeur : Variable spéciale contenant l'adresse d'une autre variable.
  • Opérateur & : Opérateur "adresse de" qui donne l'adresse d'une variable.
  • Opérateur * : Opérateur "contenu de" qui donne la valeur pointée par un pointeur.
  • Tableau : Ensemble contigu d'éléments de même type, dont le nom représente l'adresse du premier élément.
  • Arithmétique des pointeurs : Opérations d'addition, soustraction, incrémentation et décrémentation sur des pointeurs, tenant compte de la taille des éléments pointés.
  • Déclaration d'un pointeur : Syntaxe <Type> *<NomPointeur>; pour déclarer un pointeur sur un type donné.

Points clés à retenir

  • Un pointeur contient l'adresse d'une variable et permet un accès indirect à sa valeur.
  • Les opérateurs & et * sont essentiels pour manipuler les pointeurs.
  • Le nom d'un tableau est un pointeur constant vers son premier élément.
  • Les expressions tab[i] et *(tab + i) sont équivalentes.
  • L'arithmétique des pointeurs permet de naviguer dans un tableau en décalant le pointeur.
  • Les opérations sur pointeurs doivent rester dans les limites du tableau pour éviter un comportement indéfini.
  • On peut comparer et soustraire des pointeurs qui pointent dans le même tableau.
  • La manipulation des pointeurs est plus flexible que celle des noms de tableaux, qui sont des constantes.

Partager

Commentaires

Aucun commentaire pour le moment. Posez la première question.

Les commentaires sont relus avant publication. Votre e-mail n'est jamais affiché.

← Toutes les révisions