[C] pointeurs et passage de paramètres

Fermé
nadsky Messages postés 162 Date d'inscription mardi 3 juillet 2007 Statut Membre Dernière intervention 11 décembre 2011 - 20 juil. 2007 à 09:39
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 - 20 juil. 2007 à 10:02
bonjour,je suis en train de relire mes tp de 1ere année et,n'étant pas très douée surtout avec les pointeurs,je rencontre quelques difficultés de compréhension.
en effet le but du tp est de chercher le minimum et la maximum dans un tableau avec des entiers tirés aléatoirement dans[0,50]
dans le main,on crée un tableau d'entiers,dont la taille est spécifiée dans le #define,puis trois variables de travail:min,max et statut de type entier.
voici les prototypage de fonction:
void initialisationGenerateur();
void remplirTableau(int leTableau[],int nombreElements);
void afficherTableau(int leTableau[],int nombreElements);
int minMaxTableau( int leTableau[], int nombreElements, int*rangMinimum, int*rangMaximum);

les trois premières fonctions font intervenir une "copie" des variables(si j'ai bien compris),alors que la dernière intervient directement sur les adresses de variables grace aux pointeurs.
cependant,toujours dans le main,lorsqu'on recherche le maximum et le minimum,on a la ligne suivante:
statut=minMaxTableau(monTableau,TAILLE,&min,&max);
si je comprends,on met & du fait qu'on passe les adresses des variables min et max à cette fonction minMaxTableau,mais je ne comprends pas pourquoi on ne passe pas les adresses des autres paramètres pour cette fonction(celle du tableau monTableau entre autres)pour pouvoir travailler directement dessus au lieu d'en faire une copie...(j'ai d'ailleurs vu qu'il était laborieux de copier tout un tableau)
voila,j'espère que j'ai été assez claire...merci d'avance

voici la définition de la fonction minMaxTableau:
int minMaxTableau(int tab[],int nb,int *ptMin, int*ptMax)
{
int i;
if(nb==0)
return -1;
*ptMin=*ptMax=0;
for(i=1;i<nb;i++)
if(tab[i]< tab[*ptMin])
*ptMin=i;
if(tab[i]> tab[*ptMax])
*ptMax=i;
}
return 0;
}
A voir également:

2 réponses

Utilisateur anonyme
20 juil. 2007 à 09:46
on met &min,&max car dans la fonction, les valeur de min vont changer. si tu passe par par ardresses, lors de la sortie de la fonction, les valeurs changés reprendront leur valeur qe'elles avaien avant de rentrer dans la fonction.

exemple:
min=5:
max=3;
statut=minMaxTableau(monTableau,TAILLE,min,max); //on met dans cette fonction min à 10 et max à 20
printf("%d %d\n",min,max);//ca va donner 5 et 3

exemple 2:
min=5:
max=3;
statut=minMaxTableau(monTableau,TAILLE,&min,&max); //on met dans cette fonction min à 10 et max à 20
printf("%d %d\n",min,max);//ca va donner 10 et 20

voila :D
0
mamiemando Messages postés 33446 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 20 décembre 2024 7 812
20 juil. 2007 à 10:02
Les appels de fonction en C

En C tout paramètre est en fait une recopie des variables d'appel. Exemple
#include <stdio.h>

void incrementer(int x){
  ++x;
}

int main(){
  int x =2;
  incrementer(x);
  return 0;
}

... ne fait rien car le x du main est recopié lors de l'appel d'incrémenter, et la fonction incrémente cette recopie. Quand on revient dans le main, le x du main n'a pas bougé. La seule façon de modifier x, c'est de passer son adresse (concrètement on recopie son adresse, mais cette adresse px est bien celle de x : ainsi *px permet bien de modifier la valeur de x depuis incrémenter) :
void incrementer2(int *px){
  ++(*px);
}

En C++ c'est plus simple on utilise directement des références, mais ce n'est pas le sujet du jour.

Rappels sur les pointeurs

J'insiste sur le fait qu'un pointeur est TOUJOURS une adresse et fait donc TOUJOURS la même taille en mémoire. Le type d'un pointeur n'a aucune importance sauf en terme de warning c'est toujours une adresse. Le type d'une adresse générique est "void *", et l'adresse d'un plop est de type "plop *". On peut bien sur manipuler des pointeurs sur des adresses (par exemple un char ** est l'adresse d'un char * qui est l'adresse d'un char).

Pour récupérer l'adresse d'un objet plop on utilise l'opérateur & :
plop p;
plop *px = &p;

Pour récupérer l'objet (où la référence en C++) se trouvant à une adresse px, on utilise l'opérateur *:
plop *px = (plop *) malloc(sizeof(plop));
plop p = *px;

Une segmentation fault revient à évaluer le contenu d'une adresse invalide, c'est à dire qui désigne une zone qui n'a pas été allouée par ton programme (par exemple si tu as oublié de faire un malloc, et que ton pointeur n'a pas été initialisé avec une adresse valide comme par exemple l'adresse d'une variable de ton programme).

L'opérateur [] du C ne fait qu'utiliser l'opérateur * en se décalant de i cases (c'est d'ailleurs pour ca que quand i est hors du tableau ca fait une erreur de segmentation), c'est juste une façon simplifiée d'écrire les choses. C'est également pour cette raison qu'un tableau d'int est un "int *", par exemple tab[0] (ie *tab) est bien de type int.

Chercher le min et le max d'un tableau

Ici min et max doivent être modifiés par notre fonction, on doit donc passer leur adresse. On a besoin du tableau, mais aussi de sa taille, car le pointeur du tableau comme on vient de le voir ne donne que la position de sa première case en mémoire. Comme on veut s'arrêter au bout de ce tableau, il faut bien passer une information permettant de le détecter. Ici on choisit le nombre de case, mais ca aurait pu être l'adresse de la dernière case. Si un jour tu fais du C++ tu verras que c'est plus ou moins ce que font les iterators. Bref dans notre cas ça donne :
#include <stdio.h>
#include <stdlib.h>

void minmax(int *tab,unsigned taille,int *min,int *max){
  unsigned i;
  *min = tab[0];
  *max = tab[0];
  for(i=0;i<taille;++i){
    *min = tab[i] < *min ? tab[i] : *min;
    *max = tab[i] > *max ? tab[i] : *max;
  }
}

int main(){
  int min,max;
  unsigned i;
  const unsigned taille = 5;
  int *tab = (int *) calloc(taille,sizeof(int));
  // je mets des valeurs au pif dans le tableau
  for(i=0;i<taille;++i){
    tab[i] = (i-2)*i;
    printf("tab[%i] = %d\n",i,tab[i]);
  }
  minmax(tab,taille,&min,&max);
  printf("min = %d max = %d\n",min,max);
  free(tab);
  return 0;
}

Ce qui donne
(mando@aldur) (~) $ gcc -W -Wall plop.c
(mando@aldur) (~) $ ./a.out
tab[0] = 0
tab[1] = -1
tab[2] = 0
tab[3] = 3
tab[4] = 8
min = -1 max = 8

Bonne chance
0