IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Pointeur de pointeur en passage par reference.Debutant.


Sujet :

C

  1. #1
    Nouveau membre du Club
    Inscrit en
    octobre 2010
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : octobre 2010
    Messages : 49
    Points : 34
    Points
    34
    Par défaut Pointeur de pointeur en passage par reference.Debutant.
    Bonjour ,
    Je declare une matrice sous forme pointeur de pointeur dans mon main.
    Je veux allouer dynamiquement ma matrice dans une fonction incremente.
    Seulement avec le code ci dessous , j'ai un segmentation fault situé dans la fonction affiche.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    void incremente (int** mat)
    {
    int i,j,k=0;
    mat=(int**)malloc(sizeof(int*)*4);
    for (i=0;i<4;i++)
    	mat[i]=(int*)malloc(sizeof(int)*4);
     
    for (i=0;i<4;i++)
    	for(j=0;j<4;j++)
    		mat[i][j]=k++;
    }
     
    void affiche (int** mat)
    {
    int i,j;
    for (i=0;i<4;i++)
    	{
    	for(j=0;j<4;j++)
    		printf("%d\t",mat[i][j]);
    	printf("\n");
    	}
    }
     
    int main ()
    {
    int** matrice;
    matrice=(int**)malloc(sizeof(int*));
    incremente(matrice);
    affiche(matrice);
    return EXIT_SUCCESS;
    }
    Je ne comprends pas d'ou viens l'erreur , si vous pouvez m'aiguiller.
    Merci de votre aide.

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : juin 2005
    Messages : 5 761
    Points : 13 727
    Points
    13 727
    Par défaut
    La fonction affiche() n'y est pour rien : c'est le tableau qui est mal construit.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void incremente (int** mat)
    {
    ....
    mat=(int**)malloc(sizeof(int*)*4);
    ....
    }
    mat est ici une variable locale qui est initialisée par la valeur passée en argument (matrice) lors de l'appel de la fonction . Cette valeur d'initialisation est tout de suite écrasée par la valeur retournée par le malloc(), autrement dit déclarer mat en paramètre ne sert à rien. La nouvelle valeur de mat est utilisée dans la suite du code puis, à la sortie de la fonction, mat est détruite. L'argument de la fonction (matrice) lors de l'appel dans main() n'a pas changé.

    Le plus simple est de faire créer la matrice complètement dans incremente() et retourner l'adresse de la matrice obtenue:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    int** incremente (void)
    {
       int i,j,k=0;
       int ** mat=malloc(sizeof(int*)*4);
       for (i=0;i<4;i++)
    	mat[i]=malloc(sizeof(int)*4);
     
       for (i=0;i<4;i++)
    	for(j=0;j<4;j++)
    		mat[i][j]=k++;
       return mat ;
    }
    int main (void)
    {
      int** matrice = incremente();
    ....
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Nouveau membre du Club
    Inscrit en
    octobre 2010
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : octobre 2010
    Messages : 49
    Points : 34
    Points
    34
    Par défaut
    Merci pour cette réponse.
    J'ai bien compris ta version.Et c'est celle que je vais utiliser.Cependant j'aimerais mieux comprendre deux trois choses:
    mat est ici une variable locale qui est initialisée par la valeur passée en argument (matrice) lors de l'appel de la fonction .
    Ah bon?Pour moi ,je passais justement matrice(qui est une adresse) en parametre de la fonction incremente.Donc mat serait l'adresse de matrice.D'ailleurs , si il s'agissait d'une variable locale , ça serait plutôt:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void incremente (.....................)
    {
    int** mat;
    ......
    }
    Du coup je m'interroge:comment faire pour travailler directement avec un passage par adresse de matrice(ce que je croyais avoir fait) et récuperer la matrice construite à la sortie de la fonction , mais avec une fonction incremente de ce type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void incremente(int **mat)
    J'ai essaye un code de ce type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    void incremente (int*** mat)
    {
    int i,j,k=0;
    mat=(int***)malloc(sizeof(int**);
    *mat=(int**)malloc(sizeof(int*)*4);
    for (i=0;i<4;i++)
    	(*mat)[i]=(int*)malloc(sizeof(int)*4);
     
    for (i=0;i<4;i++)
    	for(j=0;j<4;j++)
    		(*mat)[i][j]=k++;
    }
     
    int main ()
    {
    int** matrice;
    incremente(&matrice);
    return EXIT_SUCCESS;
    }
    Mais l'essai n'est pas concluant , et même si cela avait été le cas , ça devient illible.Mais bon j'aimerais bien savoir comment on fait quand meme.Il y a un petit quelque choses que je n'ai pas compris là , et j'aimerais bien pouvoir mettre "le doigt" dessus.
    Merci.

  4. #4
    Membre actif Avatar de quetzacoatl
    Profil pro
    Inscrit en
    janvier 2011
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : janvier 2011
    Messages : 168
    Points : 223
    Points
    223
    Par défaut
    En fait, lorsque tu fais:
    void incremente(int **mat)
    puis que tu fais
    Il va copier la valeur de matrice dans une case mémoire
    Autrement dit la variable avec laquelle il va travailler n'est plus "matrice", c'est juste un autre double pointeur qui contient l'adresse de (*matrice) que l'on appelera ici "matrice_cpy".
    Ainsi lorsque tu fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mat=(int**)malloc(sizeof(int*)*4);
    c'est bien "matrice_cpy" qui va pointer vers la zone mémoire réservée et non "matrice"
    Donc si tu veux une solution plus lisible, opte pour celle de Diogène, sinon tu peux faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    void incremente (int*** mat)
    {
    int i,j,k=0;
    mat=(int***)malloc(sizeof(int**);/*A priori,
     lors de l'utilisation de ta fonction tu fais un passage par adresse(incremente
    (&matrice), tu as donc déja de l'espace reservé, ce malloc est donc inutile et
     peut-être même qu'il va te faire perdre ta variable*/
    *mat=(int**)malloc(sizeof(int*)*4);
    for (i=0;i<4;i++)
    	(*mat)[i]=(int*)malloc(sizeof(int)*4);
    	
    for (i=0;i<4;i++)
    	for(j=0;j<4;j++)
    		(*mat)[i][j]=k++;
    }

  5. #5
    Nouveau membre du Club
    Inscrit en
    octobre 2010
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : octobre 2010
    Messages : 49
    Points : 34
    Points
    34
    Par défaut
    lors de l'utilisation de ta fonction tu fais un passage par adresse(incremente
    (&matrice), tu as donc déja de l'espace reservé, ce malloc est donc inutile et
    peut-être même qu'il va te faire perdre ta variable
    C'est exactement ça , c'est ce malloc qui en fait me fait perdre la variable pointeur passé par référence(adresse),et qui la remplace par une variable locale(cf Diogene).
    J'avais un peu de mal avec le fait de ne pas initialiser matrice dans mon main.Mais apparemment le fait de passer (&matrice) en argument d'une fonction alloue automatiquement de la mémoire à (&matrice) sans avoir besoin de faire de malloc.Par contre il faut bien allouer (*mat) dans la fonction qui correspond à matrice dans le main.
    Enfin , si j'ai bien compris.Et si vous avez reussi à me lire.
    En tout cas,merci pour votre aide.

  6. #6
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : juin 2005
    Messages : 5 761
    Points : 13 727
    Points
    13 727
    Par défaut
    Quelques principes en C à retenir :

    1- Un paramètre d'une fonction définit une variable locale à la fonction.

    2- Lorsqu'on passe en C un argument à une fonction, on passe toujours une valeur qui devient la valeur initiale du paramètre correspondant dans la fonction (on obtient une copie de la valeur de l'argument).

    3- En conséquence, on ne peut pas passer un objet en argument d'une fonction (mais on peut passer son adresse). Si un objet est utilisé comme argument, on passe en fait la valeur de l'objet.

    Il n'y a aucune exception à ce mécanisme.

    Mais apparemment le fait de passer (&matrice) en argument d'une fonction alloue automatiquement de la mémoire à (&matrice) sans avoir besoin de faire de malloc
    Non, il n'y a pas de mémoire réservée pour &matrice. &matrice est une simple valeur, pas une variable (un objet) et n'a pas d'adresse donc de zone mémoire réservée. C'est matrice qui doit être un objet et avoir une zone mémoire allouée comme dans ton code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int** matrice;   // matrice est un objet
    incremente(&matrice); //&matrice est une valeur égale à l'adresse de l'objet matrice
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  7. #7
    Nouveau membre du Club
    Inscrit en
    octobre 2010
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : octobre 2010
    Messages : 49
    Points : 34
    Points
    34
    Par défaut
    Ok , merci pour cette précision.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Passage par reference
    Par Seth77 dans le forum Langage
    Réponses: 38
    Dernier message: 03/09/2008, 18h38
  2. [debutant(e)]passage par reference
    Par kass28 dans le forum Débuter
    Réponses: 4
    Dernier message: 27/07/2007, 18h56
  3. Probleme d'un passage par reference.
    Par mego dans le forum Langage
    Réponses: 4
    Dernier message: 19/04/2007, 17h41
  4. Probleme sur le passage par reference
    Par schnito dans le forum Langage
    Réponses: 10
    Dernier message: 02/02/2006, 17h50
  5. [VB6]Passage par référence d'une prop. d'objet à une fct
    Par -gYs- dans le forum VB 6 et antérieur
    Réponses: 15
    Dernier message: 02/09/2002, 09h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo