Vous êtes sur la page 1sur 22

Programmation II

Programmation modulaire et les


pointeurs
Pr Rachid DEHBI
Département Mathématique et
informatique
Faculté des sciences Ain chock
Année Universitaire 2014/2015
Plan

• Pointeur?
• L'opérateur d'adresse &
• Déclaration et manipulation de
pointeur
• Passage des arguments de fonctions
par adresse
• Tableaux transmis en argument

Pr DEHBI Rachid
pointeurs?
• C'est toute la puissance du langage C.
• Ils sont ni plus ni moins que des variables
contenant l'adresse d'autres variables.

Pr DEHBI Rachid
L'opérateur d'adresse &
• Il permet de connaître l'adresse de n'importe
quelle variable ou constante.

#include <stdio.h>
/* Déclaration d'un entier */
int i;
void main()
{
i=3;
/* Affichage de la valeur et de l'adresse de i */
printf("La valeur de i est %d\n",i);
printf("L'adresse de i est %d\n",&i);
}
Déclaration et manipulation de
pointeur
• Un pointeur est une variable contenant l'adresse
d'une autre variable (Indirection)
• La déclaration de pointeur se fait en rajoutant une
étoile * devant L'identificateur de pointeur.

• Syntaxe:
<classe><type>*ptr_identificateur_de_pointeur;
NB: Il est conseillé, mais pas obligatoire, de faire
commencer chaque identificateur de pointeur par
ptr_ pour les distinguer des autres variables.
Exemple

#include <stdio.h>
/* Déclaration d'un entier */
int i;
/* Déclaration d'un pointeur d'entier */
int *ptr_i;
void main()
{
/* Initialisation de ptr_i sur l'adresse de i */
printf(" l adresse %d \n",&i);
ptr_i=&i;
printf(" l adresse %d \n",ptr_i);
}
La valeur d'un pointeur
• Pour pouvoir accéder à la valeur d'un
pointeur il suffit de rajouter une étoile * devant
l'identificateur de pointeur.

• L'étoile devant l'identificateur de pointeur veut


dire objet(valeur) pointé par.
Exemple:
*ptr_i=56;
Exemple
#include <stdio.h>
/* Déclaration d'un entier */
int i;
/* Déclaration d'un pointeur d'entier */
int *ptr_i;
void main()
{
/* Initialisation de i */
i=5;
/* Initialisation de ptr_i sur l'adresse de i */
ptr_i=&i;
/* Affichage de la valeur de i */
printf("La valeur de i est %d\n",i);
/* Changement de valeur i par le pointeur ptr_i */
*ptr_i=56;
/* Affichage de la valeur de i par le pointeur ptr_i */
printf("La valeur de i est %d\n",*ptr_i);
}
Représentation mémoire

Remarque: Si vous tapez l'exemple précédant le pointeur ptr_i ne sera sûrement pas égal à
100, car c'est le système d'exploitation de la machine qui fixe l'adresse de la variable i.
Passage des arguments de fonctions
par adresse
• La transmission par référence n’existe pas en
langage C; elle est émulée par le passage par
adresse.
• Principe : On communique l’adresse d’une
variable, ce qui permet d’en modifier le contenu
(sans modifier l’adresse elle-même).
• L’adresse d’une variable est manipulée par un
pointeur.
• Les paramètres formels doivent être des
pointeurs ; les paramètres effectifs doivent
être des adresses, par exemple des noms de
variables précédés de l’operateur d’adressage &.
Exemple- Rappelons que le programme
suivant :
/* valeur_2.c */ /* adresse.c */
#include <stdio.h> #include <stdio.h>
void affiche(int n) void affiche(int *n)
{ { Son exécution fait
n = 4; *n = 4;
afficher 4 puis 4.
printf("%d \n", n); printf("%d \n", *n);
La fonction
} }
affiche() a donc
void main(void) void main(void) changé la valeur
{ {
de n dans la
int n = 3; int n = 3;
fonction
affiche(n); affiche(&n);
principale.
printf("%d \n", n); printf("%d \n", n);
} }

Avec passage des paramètres


par valeur fait afficher 4 puis 3.
Exemple: Par valeur et par adresse
#include <stdio.h> #include <stdio.h>
/* Déclaration des variables globales */ /* Déclaration des variables globales */
int a,b; int a,b;
/* Déclaration des prototypes */ /* Déclaration des prototypes */
void fonction(int val1,int val2); void fonction(int *val1,int *val2);
void fonction(int val1,int val2) void fonction(int *val1,int *val2)
{ {
val1+=4; /* Incrémente val1 de 4 */ *val1+=4; /* Incrémente val1 de 4 */
val2+-2; /* Décrémente val2 de 2 */ *val2+-2; /* Décrémente val2 de 2 */
printf("val1=%d et printf("val1=%d et
val2=%d\n",val1,val2); val2=%d\n",*val1,*val2);
} }
void main() void main()
{ {
/* Initialisation de a et b */ /* Initialisation de a et b */
a=4;b=6; a=4;b=6;
/* Premier affichage de a et b */ /* Premier affichage de a et b */
printf("a=%d et b=%d\n",a,b); printf("a=%d et b=%d\n",a,b);
/* Appel de la fonction */ /* Appel de la fonction */
fonction(a,b); fonction(&a,&b);
/* Deuxième affichage de a et b */ /* Deuxième affichage de a et b */
printf("a=%d et b=%d\n",a,b); printf("a=%d et b=%d\n",a,b);
} }
Exemple: Echange
Explication:

#include <stdio.h> • Les arguments effectifs de


main() l’appel de echange sont, cette
{
fois, les adresses des variables a
void echange (int * ad1, int * ad2) ;
int a=10, b=20 ; et b (et non plus leurs valeurs).
printf ("avant appel %d %d\n", a, b) ; • Notez bien que la transmission
echange (&a, &b) ; se fait toujours par valeur, à
printf ("après appel %d %d", a, b) ;
} savoir que l’on transmet à la
void echange (int * ad1, int * ad2) fonction echange les valeurs des
{ int x ; expressions &a et &b.
x = * ad1 ;
* ad1 = * ad2 ;
• Voyez comme, dans echange,
* ad2 = x ; nous avons indiqué, comme
} arguments muets, deux
avant appel 10 20 variables pointeurs destinées à
après appel 20 10
recevoir ces adresses.
Tableaux
• En langage C, l’identificateur d’un tableau,
lorsqu’il est employé seul (sans indices à sa
suite), est considéré comme un pointeur
(constant) sur le début du tableau.

• L'adresse du premier élément est


L'identificateur ou &identificateur[0].
• L'adresse de l'élément n est
&identificateur[n-1].
Exemple
#include <stdio.h>
/* Déclaration d'un tableau d'entiers */
int tab[3];
/* Déclaration d'une chaîne */
char nom[10]="Bonjour";
void main()
{
/* Affichage de l'adresse de tab */
printf("La valeur de tab est %d\n",tab);
printf("\t\t ou \n");
printf("L'adresse de tab est %d\n",&tab[0]);
/* Affichage de l'adresse de nom */
printf("La valeur de nom est %d\n",nom);
printf("\t\t ou \n");
printf("L'adresse de nom est %d\n",nom);
}
Les tableaux transmis en argument
• NB: Lorsque l’on place le nom d’un tableau en
argument effectif de l’appel d’une fonction, on
transmet finalement l’adresse du tableau à la
fonction, ce qui lui permet d’effectuer toutes les
manipulations voulues sur ses éléments, qu’il
s’agisse d’utiliser leur valeur ou de la modifier.
Cas des tableaux à un indice
• Voici un exemple de fonction qui met la valeur 1 dans tous les
éléments d’un tableau de 10 éléments, l’adresse de ce tableau étant
transmise en argument.
• Voici deux exemples d’appels possibles de cette fonction :
int t1[10], t2[10] :
.....
fct(t1) ;
....
fct(t2) ;

• L’en-tête de fct peut être indifféremment écrit de l’une des manières


suivantes :
void fct (int t[10])
void fct (int * t)
void fct (int t[])

• Par ailleurs, comme d’habitude, quel que soit l’en-tête employé, on


peut, dans la définition de la fonction, utiliser indifféremment le
formalisme tableau ou le formalisme pointeur.
for (i=0 ; i<10 ; i++) t[i] = 1 ;
for (i=0 ; i<10 ; i++, t++) *t = 1 ;
for (i=0 ; i<10 ; i++) *(t+i) = 1 ;
for (i=0 ; i<10 ; i++) t[i] = 1 ;
Exemple: remplissage d’un tableau

#include <stdio.h>
int t1[10];
void fct (int t[10]){
int i;
for (i=0 ; i<10 ; i++) t[i] = i ;
}

void main()
{
fct(t1);
int i;
for (i=0 ; i<10 ; i++) {
printf("La valeur de tab est %d\n",t1[i]);
}
}
Second exemple : tableau de taille
variable

• NB: lorsqu’un tableau à un seul indice apparaît


en argument d’une fonction, le compilateur n’a
pas besoin d’en connaître la taille exacte. Il est
ainsi facile de réaliser une fonction capable de
travailler avec un tableau de dimension
quelconque, à condition de lui en transmettre la
taille en argument.
Fonction travaillant sur un tableau de
taille variable
int som (int t[],int nb)
{ int s = 0, i ;
for (i=0 ; i<nb ; i++)
s += t[i] ;
return (s) ;
}
• Voici quelques exemples d’appels de cette fonction :

main()
{ int t1[30], t2[15], t3[10] ;
int s1, s2, s3 ;
.....
s1 = som(t1, 30) ;
s2 = som(t2, 15) + som(t3, 10) ;
.....
}
• l’en-tête peut préciser la dimension d’un tableau
int som (int nb, int t[nb])
• L’en-tête suivant serait rejeté :
int som (int t[nb], int nb)
Exemple
#include <stdio.h>
void somme(int n,int a[n] );
#include <stdio.h> void main(void){
void somme(int x[], int n); int i;
void main(void){ int p[6] = { 1, 2,3, 5, 7, 11 };
int i; for (i=0;i<6;i++)
int p[6] = { 1, 2,3, 5, 7, 11 }; printf("%d ", p[i]);
somme(p, 6); printf("\n",
for (i=0;i<6;i++) p[i]);
printf("%d ", p[i]); somme(6, p);
} for (i=0;i<6;i++)
printf("%d ", p[i]);
void somme(int x[], int n){ }
int i;
for(i = n-1; i >0 ; i--) void somme(int n,int a[n] ){
a[i] += a[i-1]; int i;
} for(i = n-1; i >0 ; i--)
a[i] += a[i-1];
}
Exemple de passage par adresse de tableau:
Fonction calculant la longueur d’une chaîne de
caractères
#include <stdio.h> while(*ptr_chaine!='\0')
/* Déclaration et initialisation d'une {
chaîne de caractères */ nb_car++; /* Incrémente le compteur de
char message[10]="Renéaa"; caractères */
/* Déclaration de prototype */ ptr_chaine++; /* Incrémente le pointeur
int long_ch(char *ptr_chaine); de chaîne */
int long_ch(char *ptr_chaine) }
/* Description: Donne le nombre de return(nb_car); /* Renvoie le nb de
caractères d'une chaîne */ caractères */
/* ptr_chaine : Pointeur de type char, }
pointant sur la chaîne */ void main()
/* renvoie le nombre de caractères dans un {
entier */ printf("La longueur de %s est
{ %d\n",message,long_ch(message));
/* Variable locale compteur */ }
int nb_car;
/* Initialisation du compteur */
nb_car=0;
/* Faire tant que le caractère est différent
de '\0' */

Vous aimerez peut-être aussi