CINI – Li115 1 Semaine 10 Les pointeurs ● Notion d'adresse ● Déclaration et utilisation de pointeurs ● "Types pointeur" et initialisation des pointeurs.

Slides:



Advertisements
Présentations similaires
La boucle for : init7.c et init71.c
Advertisements

Paramètres et pointeurs
FONCTIONS avec paramètres en Entrée/Sortie
Plan cours La notion de pointeur et d’adresse mémoire.
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 «
CINI – Li115 1 Semaine 2 Bibliothèque graphique, opérateurs et instructions de base ● Bibliothèque graphique ● Instruction composée ● Instructions conditionnelles.
Outils logiciel pour la programmation en C. 2 Automatiser la compilation : make make est un utilitaire présent dans toute les distribution de linux >
C++ Les fonctions. Présentation Utilité : Dès qu'un programme dépasse la centaine de lignes de code, il est pratique de pouvoir le décomposer en plusieurs.
CINI – Li115 1 Semaine 9 Algorithmes de tri ● Introduction ● Tri à bulle ● - principe ● - algorithme ● - efficacité ● Tri par sélection ● - principe, algorithme,
1 © Copyright 2005, Philippe Arlotto tln.fr Creative Commons Attribution-ShareAlike 2.0 license 25/09/2016 ● Algorithmique & Langage.
Tableaux et Pointeurs Chaînes de Caractères Programmation Impérative II.
CINI – Li115 1 Semaine 3 Boucles (suite), tirages aléatoires, bibliothèque graphique ● Imbrication d'instructions if et for ● Boucles for imbriquées ●
CINI – Li115 1 Semaine 4 Révisions ● Questions de cours ● Types des expressions ● Déclaration de variables ● Instruction conditionnelle et boucles ● Structure.
CINI – Li115 1 Introduction à la programmation impérative en langage C Module Li115 Semestre 2011fev Chargés de cours : Nicolas Sabouret Pierre Fouilhoux.
CINI – Li115 1 Semaine 6 Les fonctions ● Pourquoi écrire des fonctions ? ● Définition de fonctions ● Fonction main ● Appels de fonctions ● Portée des variables.
CINI – Li115 1 Semaine 5 Les tableaux ● Qu'est-ce qu'un tableau ? ● Déclarer et initialiser un tableau ● Fixer la taille d'un tableau ● Opérations classiques.
1 Programmation en C++ Fonctions ● Déclaration et définition de fonctions ● Arguments ● Surcharge ● Arguments optionnels ● Fonctions constantes ● Fonctions.
1 Programmation en C++ C++ de base ● Programme C++ ● Variables, objets, types ● Fonctions ● Namespace ● Tests ● Boucles ● Pointeurs, références.
1 Programmation en C++ C++ de base ● Programme C++ ● Variables, objets, types ● Types et opérations fondamentales ● Tests ● Boucles ● Pointeurs, références.
CINI – Li115 1 Semaine 11 Les pointeurs (suite) ● Tableaux et pointeurs ● Questions sur les pointeurs.
Tableaux en C Mardi 2/05.
Semaine 8 Retour sur les tableaux : fonctions et récursivité
Synthèse TP 2 Codeblock 1 Les objectifs de ce tp sont :
Les tableaux différencier les variables simples des variables indicées (ordonnées et numérotées) un identificateur unique désigne un ensemble, une collection.
Environnement de développement des BD
Introduction au Langage Pascal
Structure et Services « STS » Menu Structures : Divisions
LES TABLEAUX EN JAVA.
Pas de variable globale
Les notions de classe et d'objet
Eléments d’Informatique Cours11 – Allocation dynamique, listes chaînées Catherine Recanati.
Allocation dynamique de mémoire
Pointeurs et langage C.
Opérateurs Toute donnée informatique est stockée en mémoire sous la forme d'une combinaison de bits (mot machine). Les opérateurs bits permettent de modifier.
AO (Architecture des ordinateurs)
Ce videoclip produit par l’Ecole Polytechnique Fédérale de Lausanne
Principes de programmation (suite)
Algorithmique Langage C
11ième Classe (Mardi, 18 novembre) CSI2572
Semaine 11 Les pointeurs (suite)
Les fonctions.
Algorithmiques Abdelbasset KABOU
Matrices, déclaration en CSharp
Programmation en C++ Fonctions
SIF-1053 Architecture de ordinateurs
Arguments de la ligne de commande
Ce videoclip produit par l’Ecole Polytechnique Fédérale de Lausanne
6. Les types utilisateurs et les structures de données
Notions de pointeurs en C
Programmation en C++ Fonctions
Cours N°9: Algorithmiques Les Tableaux 1
Cours 8 5. Appels de fonctions Le matériel Concepts de pile
Programmation en C++ C++ de base
1 RECURSIVITE PRESENTATION Ch. PAUL ALGORITHMIQUE Présentation de la récursivité.
Type Concret – Type Abstrait
Assembleur ARM: Séquence d’exécution et branchements
Eléments de base du langage C
Les classes et les objets
Les structures de base Listes chainées. Listes Les listes(similaire aux tableaux) sont des structures informatiques qui permettent de garder en mémoire.
Les exceptions Le mécanisme des exceptions est destiné à permettre aux fonctions profondes d'une bibliothèque de notifier la survenue d'une erreur aux.
Position, dispersion, forme
Dépiler et mettre valeur dans RT (récup. paramètre)
Principes de programmation (suite)
Cours 8 5. Appels de fonctions Le matériel Concepts de pile
Programmation Scratch
QCM Pointeurs 2 / Q1 On considère la déclaration suivante : char *ptc ; ptc peut contenir : 1) des valeurs de variables de type caractère 2) des adresses.
Fonctions Abstractions procédurales.
* * SE CONNECTER À MON COMPTE PARTENAIRE POUR UN BAILLEUR (1/4)
Python Nicolas THIBAULT
Eléments de base du langage C
Transcription de la présentation:

CINI – Li115 1 Semaine 10 Les pointeurs ● Notion d'adresse ● Déclaration et utilisation de pointeurs ● "Types pointeur" et initialisation des pointeurs ● Fonctions : passage de paramètres par référence ● Suppression des variables globales

CINI – Li115 2 Notion d'adresse adresse : localisation d'une variable en mémoire 123 int var_a = 123 (stockée pointeur p = adresse de var_a pointeur : variable qui a pour valeur une adresse. on ne s'intéresse pas directement à la valeur d'un pointeur. on s'intéresse à la variable se trouvant à l'adresse contenue par le pointeur Notation pour la suite pour adresse de la variable de nom a

CINI – Li115 3 Déclaration *var_pointeur; var_pointeur variable de type pointeur pointeur sur une variable de type int *mon_pointeur; déclaration de la variable mon_pointeur de type pointeur sur un entier réservation de la place mémoire pour stocker une adresse Pas de réservation mémoire pour stocker l'entier

CINI – Li115 4 Utilisation Récupérer l'adresse d'une variable : &une_variable Accès à une valeur à partir d'un pointeur : *var_pointeur Attention : on accède à une valeur de type correspondant à la déclaration de mon_pointeur Déclarations ● *var_pointeur; ● une_variable; Exemple :int ma_variable = 123; int *mon_pointeur = &ma_variable; int aux = *mon_pointeur;

CINI – Li Utilisation de son adresse pour accéder à une variable int *p; ? p(adr ? int i; p = *p = -7; -7 adresse d'un entier valeur entière CINI_print_string("Valeur : "); CINI_print_int(*p); i = 65; Valeur : - 7 CINI_print_string("Valeur : "); CINI_print_int(*p); Valeur : 65 p 65 p i

CINI – Li115 6 Exemples d'utilisation int main(){ int * p1; char * p2; float * p3; int i = 12; char c = 'a'; float f = 12.9; p1 = &i; p2 = &c; p3 = &f; CINI_print_string("Affichage de la valeur de i : "); CINI_print_int(i); CINI_print_string(" ou "); CINI_print_int(*p1); CINI_newline(); CINI_print_string("Affichage de la valeur de c : "); CINI_print_char(c); CINI_print_string(" ou "); CINI_print_char(*p2); CINI_newline(); CINI_print_string("Affichage de la valeur de f : "); CINI_print_float(f); CINI_print_string(" ou "); CINI_print_float(*p3); CINI_newline(); return 0; } Affichage de la valeur de i : 12 ou 12 Affichage de la valeur de c : a ou a Affichage de la valeur de f : ou

CINI – Li115 7 Utilisation de plusieurs pointeurs int *p1, *p2; ? p1(adr ? int a,b; p1 = &a; *p1 = -3; ? p2(adr ? p1 = &b; *p1 = -7; p2 = p1; *p2 = 9; ? p1a ? ? p2 b ? p1a ? ? p2 b ? -7 p1a ? ? p2 b ?

CINI – Li115 8 Types pointeur *pointeur; *pointeur est de type var; &var adresse d'une variable de type Si ≠ alors * ≠ * *pointeur et var de même type pointeur et &var de même type Soient int *p1; float *p2; *p1 (de type int) et *p2 (de type float) ne sont pas de même type p1 et p2 ne sont pas de même type

CINI – Li115 9 Initialisation d'un pointeur valeur d'un pointeur = adresse d'une variable adresse d'une variable : - déterminée lors de l'exécution - ne peut pas être modifiée - l'utilisateur ne peut pas la choisir Initialisation d'un pointeur : - à partir d'une variable (&nom_variable) - à partir d'un autre pointeur (correctement initialisé), s'ils pointent sur une variable de même type (pointeur1 = pointeur2) (ne jamais initialiser avec un littéral (valeur numérique), il est impossible de savoir s'il s'agit bien de l'adresse d'une variable)

CINI – Li Initialisation d'un pointeur Exemples : #include int main(){ int * p1, *p2; char * p3, *p4; float * p5, *p6; int i = 12; char c = 'a'; float f = 12.9; p1 = &i; p3 = &c; p5 = &f; p2 = p1; p4 = p3; p6 = p5; return 0; }

CINI – Li Pointeurs : règles de bonne conduite La valeur d'un pointeur doit toujours correspondre à l'adresse d'une variable déclarée Initialisation par une instruction de la forme ● mon_pointeur = &ma_variable; ● avec mon_pointeur et ma_variable déclarées comme suit : ● *mon_pointeur; ● ma_variable; Initialisation par une instruction de la forme ● mon_pointeur1 = mon_pointeur2; ● avec mon_pointeur1 et mon_pointeur2 déclarées comme suit : ● *mon_pointeur1, *mon_pointeur2; ● et mon_pointeur2 a pour valeur l'adresse d'une variable déclarée

CINI – Li Récapitulatif ● Déclaration : * nom_pointeur; ● Indirection : opérateur & (donne l'adresse de la variable) ● nom_pointeur = & nom_variable; – Avec *mon_pointeur; – ma_variable; ● Déréférencement : opérateur * (donne la valeur pointée) ● * nom_pointeur ; → retourne une valeur de type ● Initialisation : ● nom_pointeur = & nom_variable; – Avec *mon_pointeur; – ma_variable; ● mon_pointeur1 = mon_pointeur2; – Avec *mon_pointeur1, *mon_pointeur2; – Et mon_pointeur2 initialisé.

CINI – Li Utilisation des pointeurs int main(){ float * p_f1, * p_f2, * p_f3 ; float f1 = 13.5, f2 =24.6; p_f1 = &f1; p_f2 = &f2; CINI_print_float(*p_f1); CINI_print_string(" "); CINI_print_float(*p_f2); CINI_print_string(" "); CINI_print_float(f1); CINI_print_string(" "); CINI_print_float(f2); CINI_newline(); p_f3 = p_f1; p_f1 = p_f2; p_f2 = p_f3; CINI_print_float(*p_f1); CINI_print_string(" "); CINI_print_float(*p_f2); CINI_print_string(" "); CINI_print_float(f1); CINI_print_string(" "); CINI_print_float(f2); CINI_newline(); return 0 ; } Les valeurs pointées par p_f1 et p_f2 ont été échangées. Les valeurs de p_f1 et p_f2 ont été échangées. Les valeurs de f1 et f2 sont inchangées.

CINI – Li Utilisation des pointeurs ● Que se passe-t-il en mémoire ? int main(){ float * p_f1, * p_f2, * p_f3 ; float f1 = 13.5, f2 =24.6; p_f1 = &f1; p_f2 = &f2; CINI_print_float(*p_f1); CINI_print_string(" "); CINI_print_float(*p_f2); CINI_print_string(" "); CINI_print_float(f1); CINI_print_string(" "); CINI_print_float(f2); CINI_newline(); p_f3 = p_f1; p_f1 = p_f2; p_f2 = p_f3; CINI_print_float(*p_f1); CINI_print_string(" "); CINI_print_float(*p_f2); CINI_print_string(" "); CINI_print_float(f1); CINI_print_string(" "); CINI_print_float(f2); CINI_newline(); return 0 ; } main p_f1 p_f2 adr p_f3 f1 f

CINI – Li Utilisation des pointeurs int main(){ float * p_f1, * p_f2 ; float f1 = 13.5, f2 =24.6, f3; p_f1 = &f1; p_f2 = &f2; CINI_print_float(*p_f1); CINI_print_string(" "); CINI_print_float(*p_f2); CINI_print_string(" "); CINI_print_float(f1); CINI_print_string(" "); CINI_print_float(f2); CINI_newline(); f3 = *p_f1; *p_f1 = *p_f2; *p_f2 = f3; CINI_print_float(*p_f1); CINI_print_string(" "); CINI_print_float(*p_f2); CINI_print_string(" "); CINI_print_float(f1); CINI_print_string(" "); CINI_print_float(f2); CINI_newline(); return 0; } Les valeurs pointées par p_f1 et p_f2 ont été échangées. Les valeurs de f1 et f2 ont été échangées. Mais les valeurs de p_f1 et p_f2 sont inchangées.

CINI – Li Un nouvel exemple ● Que se passe-t-il en mémoire ? main p_f1 p_f2 adr f3 f1 f adr int main(){ float * p_f1, * p_f2 ; float f1 = 13.5, f2 =24.6, f3; p_f1 = &f1; p_f2 = &f2; CINI_print_float(*p_f1); CINI_print_string(" "); CINI_print_float(*p_f2); CINI_print_string(" "); CINI_print_float(f1); CINI_print_string(" "); CINI_print_float(f2); CINI_newline(); f3 = *p_f1; *p_f1 = *p_f2; *p_f2 = f3; CINI_print_float(*p_f1); CINI_print_string(" "); CINI_print_float(*p_f2); CINI_print_string(" "); CINI_print_float(f1); CINI_print_string(" "); CINI_print_float(f2); CINI_newline(); return 0 ; } adr

CINI – Li Retour sur le passage de paramètres ● Jusqu'à présent les paramètres utilisés dans nos fonctions étaient passés par valeur (ou par copie) : ● dans la fonction, on travaille sur une copie des valeurs passées en paramètre ● les modifications réalisées sur ces valeurs ne sont donc pas répercutées en dehors de la fonction ● Exemple : #include void ajouteN(int val, int n){ val = val + n; } int main(){ int val = 45,n = 3; CINI_print_int(val); CINI_print_string(" "); CINI_newline(); ajouteN(val, n); CINI_print_int(val); CINI_print_string(" "); CINI_newline(); return 0; }

CINI – Li AjouteN : exécution main val n 45 3 ajoute N val n 3 45 à l'appel ajouteN(val, n) 48 après l'appel ajouteN(val, n) val = val + n;

CINI – Li Passage par valeur et par référence ● Comment faire pour que la valeur de la variable val du main soit modifiée après l'appel à ajouteN ? – → passer en paramètre non pas la valeur de val mais son adresse, c'est le passage par référence ● Exemple : #include void ajouteN(int* valAd, int n){ *valAd = *valAd + n; } int main(){ int val = 45,n = 3; CINI_print_int(val); CINI_print_string(" "); CINI_newline(); ajouteN(&val, n); CINI_print_int(val); CINI_print_string(" "); CINI_newline(); return 0; }

CINI – Li AjouteN : exécution main val n 3 ajoute N valAd n 3 45 à l'appel ajouteN(&val, n) après l'appel ajouteN(&val, adr 48 *valAd = *valAd + n;

CINI – Li Fonctions : passage de paramètres par référence Variables accessibles dans une fonction - variables globales, locales ou paramètres - variables dont on a l'adresse (et qui se trouvent encore dans la pile) Passer une adresse en paramètre - passage par référence - permet de lire et de modifier la valeur de la variable dont on a l'adresse

CINI – Li Calcul de la multiplication sans fonction #include int main() { int val1,val2,mult; /* saisie de val1 et val2 */... mult = val1 * val2 ; CINI_print_int(mult); CINI_newline(); return 0; }

CINI – Li Calcul de la multiplication avec une fonction qui retourne le résultat #include int main() { int val1,val2,mult; /* saisie de val1 et val2 */... mult = multiplication1(val1,val2) ; CINI_print_int(mult); CINI_newline(); return 0; } int multiplication1(int a, int b) { return a*b; }

CINI – Li Calcul de la multiplication avec une fonction qui ne retourne pas de valeur Il faut récupérer le résultat grâce à un paramètre #include int main() { int val1,val2,mult; /* saisie de val1 et val2 */... multiplication2(val1,val2,&mult) ; CINI_print_int(mult); CINI_newline(); return 0; } void multiplication2(int a, int b, int *res) { *res = a*b; }

CINI – Li Multiplication : exécution main val1 val2mult adr après saisie 45 3 multiplication2 a bres 3 à l'appel multiplication2(val1,val2,&mult)

CINI – Li main val1 val2mult adr après saisie 45 3 multiplication2 a bres 3 *res = a * b 135 après appel de mutiplication multiplication2 a *res = a * b

CINI – Li Calcul de la division euclidienne fonction qui calcule le quotient et le reste de la division de deux entiers positifs a = b * quotient + reste (reste < a) la fonction calcule deux résultats : - obligation de transmettre (au moins) un des résultats par un paramètre - nous choisissons de transmettre les deux résultats en paramètres la fonction prend 4 paramètres : - les entiers a et b - les adresses des variables représentant le quotient et le reste

CINI – Li Calcul de la division euclidienne #include void div_euclid(int a, int b, int *q, int *r) { } int main() { int val1,val2,quot,res; /* saisie de val1 et val2 */... CINI_print_int(quot); CINI_newline(); CINI_print_int(res); CINI_newline(); return 0; } div_euclid(val1,val2,&quot,&res) ; *q = a / b; *r = a % b;

CINI – Li Division euclidienne : exécution main val1 val2 quot après saisie 67 7 div_euclid a b q 7 à l'appel div_euclid(val1,val2,&quot,&res) res

CINI – Li main val1 val2 quot après saisie 67 7 div_euclid a b q 7 à l'appel div_euclid(val1,val2,&quot,&res) res *q = a / b 9 *r = a % b 4 après appel de div_euclid 67 7 div_euclid a b à l'appel div_euclid(val1,val2,&quot,&res) *q = a / b *r = a % b Division euclidienne : exécution

CINI – Li Cas d'utilisation du passage par référence ● Le passage par référence est utilisé : ● Si on souhaite modifier une variable déclarée en dehors de la fonction : on passe l'adresse de cette variable en paramètre Par exemple : exemple précédent sur la multiplication → on souhaite modifier une variable déclarée dans la fonction main. ● Si on souhaite que la fonction retourne plusieurs résultats : ajouter autant de paramètres que de résultats Par exemple : fonction calculant le reste et le quotient de la division euclidienne (cf. exemple précédent), fonction calculant les racines d'un polynôme du second degré, fonction calculant le min et le max d'un tableau,... ● Afin d'éviter la recopie de structures importantes (plus de détails dans les UE LI215 et LI213) : on passe en paramètre l'adresse de la structure plutôt que la structure complète → gain en efficacité.

CINI – Li Fonctions et pointeurs : règles de bonne conduite Une fonction ne produit jamais comme résultat l'adresse d'une de ses variables locales (aussi bien comme valeur d'un paramètre passé par référence qu'en valeur de retour) Pourquoi ? Variable locale à une fonction accessible tant que la fonction n'est pas finie son adresse n'est plus pertinente une fois la fonction finie (et l'espace associé libéré dans la pile) L'adresse est alors inutilisable de là où l'appel à la fonction a été effectué

CINI – Li Vers la suppression des variables globales Remplacer chaque variable globale par une variable locale (déclarée dans la fonction main en général) Ajouter un paramètre aux fonctions (autres que main) qui utilisaient la variable globale - passage par valeur si la fonction ne fait que lire la valeur de la variable - passage par référence si la fonction modifie la valeur de la variable

CINI – Li Variables globales : exemple #include int a, b; void f() { b = a*2; } void g() { b = b*a; a = a*2; } int main() { a=2; b=7; f(); g(); CINI_print_int(a); CINI_newline(); CINI_print_int(b); CINI_newline(); return 0; } Affichage 4 8 ab 27 b est modifiée par f() 4 a et b sont modifiées par g() 84

CINI – Li Variables globales : suppression #include int a, b; void f() { b = a*2; } void g() { b = b*a; a = a*2; } int main() { a=2; b=7; f(); g(); CINI_print_int(a); CINI_newline(); CINI_print_int(b); CINI_newline(); return 0; } void f(int v1, int *p1) { *p1 = v1*2; } f(a,&b); void g(int *p1, int *p2) { *p2 = *p2 * *p1; *p1 = *p1 * 2; } g(&a,&b); int a=2, b=7;

CINI – Li Variables globales ou paramètres par référence ? Une variable globale est utilisable partout dans le programme Plus d'inconvénients que d'avantages => NE PAS UTILISER DE VARIABLES GLOBALES mais il est difficile de comprendre comment la valeur d'une variable globale évolue - compréhension du programme difficile - modification du programme difficile - localisation d'une erreur difficile lorsqu'elle porte sur la valeur d'une variable globale