Rechercher : dans
Par :

[C] pointeurs et passage de paramètres

Dernière réponse le 20 jui 2007 à 10:02:43 nadsky, le 20 jui 2007 à 09:39:39 
 Signaler ce message aux modérateurs

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;
}

Configuration: Windows XP
Internet Explorer 7.0

Meilleures réponses pour « [C] pointeurs et passage de paramètres » dans :
Les fonctions en C++ : surcharge et paramètres par défaut. Voir Les fonctions en C++ : surcharge et paramètres par défaut. 1. La surcharge de fonctions et méthodes de classes, dont le constructeur 2. Utilisation des paramètres par défaut En C++, une même fonction ou méthode de classe peut être...
Bash - Les paramètres VoirIntroduction Les paramètres positionnels Exemple 1 Les paramètres spéciaux Exemple 2 Initialiser des paramètres - La commande "set" - Exemples - La commande "shift" - Exemple 3 Introduction Il est possible de fournir à un script,...
Les pointeurs en langage C VoirDéfinition d'un pointeur Un pointeur est une variable contenant l'adresse d'une autre variable d'un type donné. La notion de pointeur fait souvent peur car il s'agit d'une technique de programmation très puissante, permettant de définir des...
Les objets en langage C++ VoirLa création d'objets En C++, il existe deux façons de créer des objets, c'est-à-dire d'instancier une classe : de façon statique de façon dynamique La création statique La création statique d'objets consiste à créer un objet en lui affectant un...

1

coucou_c_julien, le 20 jui 2007 à 09:46:54

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

Répondre à coucou_c_julien

2

 mamiemando, le 20 jui 2007 à 10:02:43

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

Répondre à mamiemando
Collection CommentÇaMarche.net