8PRO107 Éléments de programmation Les adresses et les pointeurs.

Slides:



Advertisements
Présentations similaires
Premier programme en C :
Advertisements

La boucle for : init7.c et init71.c
Introduction au Langage C,C++
C++ 6ème cours Patrick Reuter maître de conférences
Calculs de complexité d'algorithmes
GEF 243B Programmation informatique appliquée Expressions et opérateurs §
GEF 243B Programmation informatique appliquée Expressions et opérateurs.
GEF 243B Programmation informatique appliquée
C.
Paramètres et pointeurs
Structures et unions types énumérés Qu'est-ce qu'une structure
Les pointeurs Manipulation d'adresses et de ce qui est contenu dans ces adresses Très important, fondamental même en C mauvaise réputation : 'dur à comprendre',
8. Les tableaux P. Costamagna – ISEN N1.
Introduction à la programmation (420-PK2-SL) cours 15 Gestion des applications Technologie de linformation (LEA.BW)
Points importants de la semaine Les fonctions. La portée. La passage par copie. Les tableaux.
Points importants de la semaine Les types arithmétiques. Les opérateurs.
Regrouper des éléments de même type et pouvoir y accéder à laide dun identificateur et dun indice. Objectif des tableaux.
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées
Partie 1 Etude de l'existant
Récursivité.
Points importants de la semaine Les boucles. Les types arithmétiques. Les opérateurs.
8PRO100 Éléments de programmation Allocation dynamique de la mémoire.
TRAITEMENT DE STRUCTURES
IFT-2000: Structures de Données Listes chaînées Dominic Genest, 2009.
Quest-ce quune classe dallocation? Une classe dallocation détermine la portée et la durée de vie dun objet ou dune fonction.
Les pointeurs Enormément utilisé en C/C++ ! Pourquoi? A quoi ça sert?
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
Test et débogage Tests unitaires. Gestion d’erreurs. Notion d’état, de pré-condition et de post-condition. Assertion. Traces de programme. Débogueur et.
Structures de données IFT-2000
Sixième cours Les chaînes de caractères et le passage de paramètres par référence Passage de paramètres par référence String.h.
8PRO100 Éléments de programmation Les types composés.
Les Opérateurs Ils régissent toutes les opérations ou transformations sur les valeurs des variables. Opérateur d'affectation Opérateurs arithmétiques Opérateurs.
Plan cours La notion de pointeur et d’adresse mémoire.
Types de données fondamentaux
La librairie assert.h.
L’essentiel du langage C
2.1 - Historique Chapitre 2 : Introduction au langage C++
Le langage C Rappel Pointeurs & Allocation de mémoire.
Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques
et quelques rappels sur certains éléments du langage C
Les adresses des fonctions
SIF-1053 Architecture des ordinateurs
Un survol du language C.
1 Structures des données. 2  Le tableau permettait de désigner sous un seul nom un ensemble de valeurs de même type, chacune d'entre elles étant repérée.
Cours C++ Fonctions Surcharge d’opérateurs Passage d’arguments
Les types composés Les enregistrements.
8PRO100 Éléments de programmation Les pointeurs de caractères.
B.Shishedjiev - Affectation1 Expressions et affectation Comment produire des nouvelles valeurs.
Chapitre VII Techniques plus avancées à travers le concept de classe.
Conception de Programmes - IUT de Paris - 1ère année Quelques éléments du langage C++ Les références La surcharge de fonctions Les fonctions «
Introduction au langage C Structures de données
8PRO107 Éléments de programmation Les tableaux. Étude de cas 1 Description du problème : Lire une liste d’entiers et l’afficher d’abord dans le même ordre.
PRO-1027 Programmation Scientifique en C
Algorithmique Tableaux de données
Langage de Programmation Orientée Objet : C++
Philippe Gandy - 22 septembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Exercices sur les pointeurs. lireCar/remettreCar Lorsque l’on lit caractère par caractère, on ne peut pas savoir qu’on a atteint un caractère avant de.
Objets et Actions Élémentaires.
3ième Classe (Mardi, 23 Septembre) CSI2572. O jourd'8: E Allocation de mémoire E Déallocation de mémoire E Tableaux (n dimensions) E Arithmetique des.
Philippe Gandy – 10 novembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Introduction au langage C
C++ BY AURÉLIEN MODULO MARION. PLAN DES TROIS PRÉSENTATIONS C++ avancé C++ orienté objet Bases de C++
Informatique 2A Langage C 5ème séance. Déroulement de la séance 5 1 ère partie Étude des chaînes de caractères 2 ème partie Les structures 3.
Informatique 1A Langage C 6 ème séance 1. Objectifs de la séance 6  Allocation dynamique de mémoire  Application à la création de tableaux 2.
Informatique 2A Langage C 3 ème séance.
M. BENJELLOUN : 2005 Le but final est de programmer un jeu où l'ordinateur choisira un nombre aléatoire entre 0 et 100 que vous devez deviner.
Transcription de la présentation:

8PRO107 Éléments de programmation Les adresses et les pointeurs

Les adresses Les cases mémoire ont toutes un numéro qui les distingue les une des autres. Ce numéro est appelé adresse. C’est par cette adresse que le processeur peut communiquer avec la mémoire. 1 2 3 4 . . max

Les adresses et les variables Le nom que l’on donne aux cases mémoire est traduit en une adresse juste avant l’exécution d’un programme. Cela est nécessaire afin que le processeur sache à quelle case mémoire est associée chaque variable. En général, il est impossible de prévoir à quelle adresse sera placée une variable. Le nom des variables est donc nécessaire. c1: 1 char c1 = c2 ; Lire le contenu de la case 3. Mettre ce qui a été lu dans la case 1. 2 c2: 3 1324 char 4 . . max

Les adresses et les variables Le nom que l’on donne aux cases mémoire est traduit en une adresse juste avant l’exécution d’un programme. Cela est nécessaire afin que le processeur sache à quelle case mémoire est associée chaque variable. En général, il est impossible de prévoir à quelle adresse sera placée une variable. Le nom des variables est donc nécessaire. c1: 1 1324 char c1 = c2 ; Lire le contenu de la case 3. Mettre ce qui a été lu dans la case 1. 2 c2: 3 1324 char 4 . . max

Le partage de la mémoire Sur les systèmes modernes il peut y avoir plusieurs usagers se partageant la mémoire et chaque usager peut exécuter plusieurs programmes simultanément. Cela signifie que l’on n’est pas libre d’utiliser toutes les cases mémoire comme on le veut. Une case peut être occupée par un programme à un certain moment et libre à un autre. Cette situation est aléatoire. Pour cette raison, on ne mentionne jamais explicitement une adresse dans un programme même si cela est théoriquement possible.

Adresses valides et non valides Exemple. Dans le pseudo-code suivant: Lire le contenu de la case 3. Mettre ce qui a été lu dans la case 1. Que se passe-t-il si, au moment de l’exécution, la case mémoire 1 est déjà utilisée par un autre programme? La case est alors non valide et il y aura erreur à l’exécution. C’est pour cette raison que l’on utilise des variables. Avant l’exécution, une adresse valide est associée à chaque variable. Seul notre programme pourra utiliser ces cases mémoire.

Position des variables dans la mémoire c int . . Sauf pour les tableaux, il n’y a aucune garantie que les variables occupent des cases adjacentes en mémoire. Exemple: int a, b[4], c, d[3] ; b[0] int b[1] int b[2] int b[3] int int a . . d[0] int d[1] int d[2] int . .

Les adresses et les types Une des principales fonctions des types est d’indiquer le nombre d’octets utilisés par une variable. Par exemple nous avons vu que: un caractère prend 1 octet (8 bits) un entier prend 4 octets (32 bits). Cela signifie que si on divise la mémoire en case d’un octet alors: un char utilise 1 case un int utilise 4 cases adjacentes n: 0 00000000 int 1 00000000 2 00000000 3 00001101 c1: 4 00011011 char c2: 5 . 00011100 char . . max

Remarque On peut aussi voir la mémoire comme une suite de cases de taille variable. n: 0 00000000000000000000000000001101 int int c1: 4 00011011 char c2: 5 . 00011100 char . . max

Les adresses et les tableaux Le nom d’un tableau correspond à l’adresse du début du tableau. Exemple: char tab[5]; printf("%p\n", tab); 4027630992 printf("%p\n", tab+1); 4027630993 printf("%p\n", tab+2); 4027630994 Note: "%p" sert à afficher les pointeurs.

Les tableaux d’entiers Exemple: int tab[5] ; cout << tab ; 4027630976 cout << tab+1 ; 4027630980 cout << tab+2 ; 4027630984 Question: Pourquoi? +4 +4

L’incrémentation d’une adresse L’adresse a+1 n’est pas valide a: 16216 int . . b[0]: b=24600 int b[1]: b+1=24604 int Incrémenter une adresse ne veux pas dire ajouter 1, cela veut dire aller à l’adresse suivant la variable courante. En général cela n’a du sens que si on est dans un tableau. b[2]: b+2=24608 int b[3]: b+3=24612 int . . d[0]: d=54316 char d[1]: d+1=54317 char d[2]: d+2=54318 char . .

Remarque Si tab est un tableau alors L’adresse de tab[0] est tab, etc. Cela est vrai quel que soit le type des éléments de tab.

L’opérateur & Il est possible de connaître, pendant l’exécution d’un programme, l’adresse associée à une variable. En C++, cela se fait à l’aide de l’opérateur unaire & Exemple: char c; int n, tab[1000]; L’adresse de c est &c L’adresse de n est &n L’adresse de tab[3] est &tab[3]

Détail important Exemple: tab[1000]; L'adresse de tab[0] est &tab[0] ou encore tab ou encore &tab Il n'y a aucune différence entre &tab[0] et tab puisque tab est (par définition) l'adresse de la première case du tableau. Mais il y a une différence subtile entre tab et &tab car &tab est l'adresse de tout le tableau.

Détail important (suite) Le code suivant: int tab[10]; cout << tab << " " << tab+1 << endl; cout << &tab[0] << " " << &tab[0]+1 << endl; cout << &tab << " " << &tab+1 << endl; affichera ce qui suit: 1245016 1245020 1245016 1245056 Note: Les adresses seront écrites en hexadécimal plutôt qu'en décimal comme dans cet exemple.

L’opérateur * Il est aussi possible de connaître, pendant l’exécution d’un programme, le contenu de la case mémoire située à une adresse donnée. En C++, cela est possible à l’aide de l’opérateur unaire * Exemple: char c ; int tab[1000] ; Le contenu de l’adresse tab + 25 est *(tab + 25) *(tab + 25) est donc identique à tab[25] *(&c) est identique à c *c n’a aucun sens

Exemple Les expressions logiques suivantes sont vraies: &n == 12556 *(12560) == 60 *(12560) < c2 *(&r) == 12.345 . . n: 12556 5000000 int c1: 12560 60 char c2: 12561 61 char r: 12562 12.345 double . .

Opérations permises sur les adresses On peut: Additionner une adresse et un entier Déterminer l’adresse d’une variable Déterminer le contenu d’une adresse Soustraire deux adresses d'un même tableau On ne peut pas Additionner deux adresses

Les pointeurs Un pointeur est une variable pouvant contenir une adresse. Exemple: int *pn; pointeur sur une valeur entière char *pc; pointeur sur un caractère double *pr; pointeur sur un réel

Les pointeurs: exemple pn: 12556 int* Exemple: int *pn, m ; . . m: 65710 int . .

Les pointeurs: exemple pn: 12556 65710 int* Exemple: int *pn, m ; pn = &m ; . . m: 65710 int . .

Les pointeurs: exemple pn: 12556 65710 int* Exemple: int *pn, m ; pn = &m ; m = 6 ; . . m: 65710 6 int . .

Les pointeurs: exemple pn: 12556 65710 int* Exemple: int *pn, m ; pn = &m ; m = 6 ; *pn = 38 ; . . m: 65710 38 int . .

Les pointeurs et les tableaux En C++ les pointeurs sont intimement liés aux tableaux. Exemple: int tab[11], *p ; p = tab ; tab[3] = 70 ; *(tab + 3) = 70 ; p[3] = 70 ; *(p + 3) = 70 ; tous équivalent: tab: 1 2 3 4 5 6 7 8 9 10 p: 70

Remarque Le nom d’un tableau est une adresse constante et non pas un pointeur qui est une variable. Exemple: int tab[11], *p ; p = tab ; /* Valide */ tab = p ; /* Non valide */ tab: 1 2 3 4 5 6 7 8 9 10 p:

Quelques utilités des pointeurs Pour implanter le passage de paramètres par référence Pour implanter le passage de tableaux en paramètre Pour utiliser des indices négatifs avec les tableaux Fondamental en structure de données

Les pointeurs comme paramètres b En C++: echanger(a, b) void echanger ( int &x, int &y ) { int tmp ; tmp = x ; x = y ; y = tmp ; } x y tmp

Les pointeurs comme paramètres b En C: echanger(&a, &b) void echanger ( int *x, int *y ) { int tmp ; tmp = *x ; *x = *y ; *y = tmp ; } x y tmp &a &b

Les tableaux passés en paramètre Une des plus importantes utilisations des pointeurs réside dans le passage des tableaux en paramètre. Lorsque l’on passe le nom d’un tableau en paramètre, on passe une adresse. La fonction appelée reçoit donc une adresse qu’elle met dans une variable: cette variable doit donc être un pointeur.

Les tableaux passés en paramètre void liretab ( int tab[], int max ) { int c ; int i = 0 ; while ( (c = getchar() ) != EOF ) tab[i] = c ; i = i + 1 ; }

Les tableaux passés en paramètre void liretab ( int *tab, int max ) { int c ; int i = 0 ; while ( (c = getchar() ) != EOF ) *(tab+i) = c ; i = i + 1 ; }

Pour tester #include <iostream> using std::cout ; using std::endl ; void liretab ( int tab[] , int max ) { int c ; int i = 0 ; while ( (c = getchar() ) != EOF && i < max ) tab[i] = c ; i = i + 1 ; } void ecriretab ( int tab[] , int max ) while ( tab[i] != 0 && i < max ) cout << char(tab[i]) << " " ; cout << endl ; void liretab2 ( int * tab , int max ) *(tab+i) = c ; void ecriretab2 ( int *tab , int max ) { int i = 0 ; while ( *(tab+i) != 0 && i < max ) cout << char(*(tab+i)) << " " ; i = i + 1 ; } cout << endl ; int main () const int MAX = 100 ; int vec [MAX] = { 0 } ; liretab(vec, MAX) ; ecriretab(vec, MAX) ; liretab2(vec, MAX) ; ecriretab2(vec, MAX) ; return 0 ;

Les indices de tableaux Exemple 1 Tableau d’entiers dont les indices vont de -5 à 5: int tab[11] ; int *ptab ; ptab = tab + 5; ptab[0] est identique à tab[5] ptab[-5] est identique à tab[0] ptab[5] est identique à tab[10] 1 2 3 4 5 6 7 8 9 10 tab: ptab:

Les indices de tableaux Exemple 2 Tableau d’entiers dont les indices vont de ‘A’ à ‘Z’: int tab[26] ; int *ptab ; ptab = tab – 'A' ; /* A vaut 65 en ASCII */ ptab['A'] est identique à tab[0] ptab['Z'] est identique à tab[25] -65 1 2 3 4 21 22 23 24 25 tab:  ptab:

Les pointeurs et les tableaux à plusieurs dimensions int mat[N][M] ; mat[i][j] = 0 ; *(mat + M*i + j) = 0 ; C'est pourquoi, lors d'un appel de fonction: void f ( int mat[][M] ) {...} il est nécessaire d'indiquer le nombre de colonnes. { identique:

Les structures et les pointeurs L’opérateur de prise d’adresse & fonctionne avec les structures. On peut définir des pointeurs sur des types composés. complexe *pc, x ; pc = &x ; (*pc).reel = 3 ; (*pc).imag = 5 ; Remarque: Les parenthèses sont nécessaires puisque l’opérateur . a une priorité supérieure à l’opérateur *.

Les structures et les pointeurs Les pointeurs de structures sont si fréquemment utilisés qu’il existe une notation abrégée. Exemple: complexe *p, x ; pc = &x ; pc->reel = 3 ; /* identique à (*pc).reel=3 */ pc->imag = 5 ; /* identique à (*pc).imag=5 */