Rappel: les pointeurs en C - run.montefiore.ulg.ac.be · A ette fin, on utilise des pointeurs vers...

16
Rappel: les pointeurs en C INFO2009 Introduction à l’informatique Année académique 2017-2018

Transcript of Rappel: les pointeurs en C - run.montefiore.ulg.ac.be · A ette fin, on utilise des pointeurs vers...

Rappel: les pointeurs en C

INFO2009 – Introduction à l’informatique

Année académique 2017-2018

Qu’est-ce qu’un pointeur ?

Il s’agit d’une variable contenant l’adresse d’une autre variable.

Dans l’exemple (simplifié) suivant… x est la variable (par exemple, un entier)

y est un pointeur vers x

y est donc égal à 10

Mémoire

x y

10 11 12 13 14 15 16 17

1

Qu’est-ce qu’un pointeur ? (2)

Analogie: un panneau sur une autoroute. Il donne une information sur la position d’une ville.

Le panneau lui-même n’est pas une ville!

2

Qu’est-ce qu’un pointeur ? (3)

Plus formellement, en C…

T étant un type, T* désigne un pointeur vers une variable de type T.

L’opérateur * (dit « de déréférencement »), placé à gauche d’un pointeur, permet de récupérer la valeur qui se trouve à l’adresse pointée.

L’opérateur & (dit « de référencement »), placé à gauche d’une variable, permet d’en récupérer l’adresse.

3

Qu’est-ce qu’un pointeur ? (4)

Si x est un pointeur (type: int*) vers y (int)…

L’expression x désigne l’adresse de y

L’expression (*x) désigne la valeur de y

Si x est une variable de type int…

L’expression x désigne la valeur de x

L’expression &x désigne l’adresse de x

4

Les effets du pointeur

Prenons le code suivant:

Que vaut x après l’instruction 3 ?

1. int x = 36, y = 24;

2. int z = pgcd(x, y);

3. x += y;

int pgcd(int a, int b)

{

while (b != 0)

{

int tmp = b;

b = a % b;

a = tmp;

}

return a;

}

5

Les effets du pointeur

Prenons le code suivant:

Que vaut x après l’instruction 3 ? 60 (36 + 24) !

1. int x = 36, y = 24;

2. int z = pgcd(x, y);

3. x += y;

int pgcd(int a, int b)

{

while (b != 0)

{

int tmp = b;

b = a % b;

a = tmp;

}

return a;

}

6

Les effets du pointeur (2)

Lorsqu’on entre dans une fonction/procédure, le code appelant est suspendu.

Les valeurs des paramètres (variables ou constantes) de la fonction/procédure sont copiées au moment d’exécuter le code de la fonction/procédure.

On parle de passage par valeur.

Les variables d’origine qui ont servi de paramètres ne sont PAS manipulées.

Ce pourquoi x vaut 60 (36 + 24) et non 36 (12 + 24).

7

Les effets du pointeur (3)

Si on passe un pointeur plutôt qu’une variable…

La valeur du pointeur (une adresse) est copiée…

… mais elle pointe toujours vers cette variable.

On peut donc manipuler cette variable.

De manière informelle, cela revient à dire à la fonction où se trouve la variable pour qu’elle puisse la lire et la modifier, plutôt que d’utiliser une copie.

8

Les effets du pointeur (4)

Modifions notre exemple:

Que vaut x après l’instruction 3 ? 36 (12 + 24) !

1. int x = 36, y = 24;

2. pgcdPtr(&x, y);

3. x += y;

void pgcdPtr(int *a, int b)

{

while (b != 0)

{

int tmp = b;

b = (*a) % b;

(*a) = tmp;

}

}

9

A quoi ça sert ?

On peut retourner plusieurs résultats avec une seule et même fonction.

A cette fin, on utilise des pointeurs vers ce qu’il faut modifier: on parle de passage par adresse.

passage par adresse passage par valeur (copie de la valeur)

void pgcdPtr(int *a, int b)

{

}

10

A quoi ça sert ? (2)

Vous connaissez déjà une fonction utilisant le passage par adresse: scanf() !

Et pourquoi pas printf() ?

int a = 0, b = 0;

printf("Entrez deux entiers: ");

scanf("%d %d", &a, &b);

printf("Vous avez entré: %d, %d\n", a, b);

11

A quoi ça sert ? (2)

Vous connaissez déjà une fonction utilisant le passage par adresse: scanf() !

Et pourquoi pas printf() ?

printf() n’est pas censé modifier les variables, donc un passage par valeur suffit amplement.

int a = 0, b = 0;

printf("Entrez deux entiers: ");

scanf("%d %d", &a, &b);

printf("Vous avez entré: %d, %d\n", a, b);

12

A quoi ça sert ? (3)

Il est possible d’allouer des zones de mémoire de la taille qu’on veut pour y placer tableaux, structures…

malloc() (note: inclure stdlib.h au préalable)

reçoit en paramètre la taille en octets de la zone à allouer

retourne un pointeur vers la zone de mémoire allouée

sizeof()

retourne la taille en octets requise pour un type donné

malloc(sizeof(int) * 10) retourne un pointeur vers un bloc de 10 entiers.

13

A quoi ça sert ? (4)

Connaître l’adresse de ces zones de mémoire plutôt que ce qu’elles contiennent est plus flexible.

Cela permet de créer des structures de données avancées.

Ce sujet est abordé par d’autres cours (dont INFO0902).

N.B.: à la fin d’un programme, tout bloc alloué grâce à malloc() doit être libéré avec free(), tout comme il faut utiliser fclose() après avoir manipulé un fichier.

N.B. n°2: ne pas oublier, aussi, de vérifier la valeur de retour d’un appel à malloc() avant usage!

14

Pointeurs et tableaux

Si on alloue un bloc continu de variables d’un même type, cela équivaut à allouer un tableau.

L’opérateur d’indice [] peut s’utiliser à droite d’un pointeur pour sélectionner un élément d’un bloc continu (0 = premier élément, 1 = second, etc.).

int *arr = malloc(sizeof(int) * 10);

arr[2] = 42;

printf("%d\n", arr[2]); // Affiche « 42 »

16