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 :

structure en paramètre d'une fonction


Sujet :

C

  1. #1
    Membre régulier Avatar de Tex-Twil
    Inscrit en
    Avril 2004
    Messages
    447
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 447
    Points : 122
    Points
    122
    Par défaut structure en paramètre d'une fonction
    Bonjour,
    j'ai du mal à passer l'adresse (pointeur) d'une structure en paramètre d'une fonction qui en modifie le contenu. Je veux que les modifications soient prises en compte dans le programme appelant.

    Ce code là MARCHE:
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    typedef struct
    {
    	int *a;		// pointeur d'entiers
    } myStruct;
     
    int main()
    {
    	void test(myStruct *s);		// modifie la valeur de a
    	myStruct *s;
     
    	s = malloc(sizeof(myStruct));
    	test(s);
    	printf("s: %i\n", *(*s).a);
    	free((*s).a);
    	free(s);
     
    	return EXIT_SUCCESS;
    }
    void test(myStruct *s)
    {
    	(*s).a = malloc(sizeof(int));
    	*(*s).a = 1;
    	printf("s: %i\n", *(*s).a);
    }
    Maintenant je veux passer en paramètre la structure DH ( http://www.openssl.org/docs/crypto/dh.html# ) dans le programme suivant mais ça ne marche pas
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
     
    #include <openssl/dh.h>
    #include <openssl/engine.h>
     
    #define PRIME_LEN  64
    #define GENERATOR 2
     
    int main()
    {
    	void printDH(char *name, DH *dh);
    	void test(DH *dh); // modifie les champs de dh
     
    	DH *dhAlice;
    	srand( (unsigned)time( NULL ) );
     
    	dhAlice = DH_new();
     
    	test(dhAlice);
    	printDH("Main", dhAlice); 	// MARCHE PAS :(
    	DH_free(dhAlice);
     
    	return EXIT_SUCCESS;
    }
    void test(DH *dh)
    {
    	printf("Generating DH params ... this can take a while \n");
    	dh = DH_generate_parameters(PRIME_LEN, GENERATOR, NULL, NULL);
     
    	printf("Generating public & private keys ... \n");
    	DH_generate_key(dh);
    	printDH("Alice", dh);  // MARCHE
    }
     
    void printDH(char *name, DH *dh)
    {
         //char *BN_bn2dec(const BIGNUM *a);
        printf("--------------\n");     
        printf("%s :\n", name);
        printf("%i bits\n", PRIME_LEN);
        if(dh->p != NULL)
    		printf("p: %s\n", BN_bn2hex(dh->p));
    	else
    		printf("p: NULL\n");
     
        printf("g: %s\n", BN_bn2hex(dh->g));
        printf("priv_key: %s\n", BN_bn2hex(dh->priv_key));
        printf("pub_key: %s\n", BN_bn2hex(dh->pub_key));
    	printf("\n");         
    }
    A la sortie de la fonction, les champs de dhAlice sont nuls alors qu'ils ne l'étaient pas dans la fonction test.

    merci d'avance [/b]

  2. #2
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    C'est un problème de compréhension du C.

    Le C fait du passage de paramètre par copie.

    Reprenons donc ta fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void test(DH *dh) 
    { 
       printf("Generating DH params ... this can take a while \n"); 
       dh = DH_generate_parameters(PRIME_LEN, GENERATOR, NULL, NULL); 
     
       printf("Generating public & private keys ... \n"); 
       DH_generate_key(dh); 
       printDH("Alice", dh);  // MARCHE 
    }
    dh est local à ta fonction, c'est à dire que tout ce que tu modifies sera perdu à la fin de ta fonction.

    Si tu veux modifier dh, il faut ruser :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void test(DH **dh) 
    { 
       printf("Generating DH params ... this can take a while \n"); 
       *dh = DH_generate_parameters(PRIME_LEN, GENERATOR, NULL, NULL); 
     
       printf("Generating public & private keys ... \n"); 
       DH_generate_key(*dh); 
       printDH("Alice", *dh);  // MARCHE 
    }
    et lors de l'appel, tu fais :

    PS : n'oublie pas de tester les retours de malloc

  3. #3
    Membre régulier Avatar de Tex-Twil
    Inscrit en
    Avril 2004
    Messages
    447
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 447
    Points : 122
    Points
    122
    Par défaut
    mais pourquoi pour le premier programme ça marche ?

    pourquoi certaines fonctions de la librairie DH l'utilisent comme moi dans le deuxième programme ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int    DH_generate_key(DH *dh);
    A la sortie de cette fonction de la lib DH, dh est modifié.

  4. #4
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    (*s).a = malloc(sizeof(int));
    ici on est d'accord, c'est ce qui est pointé à l'adresse s qui est modifié et non pas s directement, un exemple simple, si tu fais s = NULL, tu pourras te rendre compte qu'après la fonction, s ne vaudra pas NULL.

    pourquoi certaines fonctions de la librairie DH l'utilisent comme moi dans le deuxième programme ?
    Tu ne sais pas comment sont codée les fonctions, ce qui est sur c'est qu'elle ne modifient pas dh mais ce qui est pointé à l'adresse dh.

    En fait, si tu veux résumer c'est simple, un pointeur est une adresse mémoire, par conséquent, c'est un entier, regarde donc une fonction qui veut modifier un entier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void modifie( long a )
    {
         a = 5;
    }
    maintenant, si tu veux, on prend cette séquence d'instruction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    long n = 10;
    modifie(n);
    printf("%l",n);
    Tu remarqueras que n n'est pas modifé, tout simplement parce que a est local à la fonction et que l'appel à crée une copie de n mais à aucun moment a et n sont les mêmes objets, ils ont la même valeur mais la ressemblance s'arrête là.

    Et bien ceci, c'est exactement ce qui se passe dans ta fonction test du programme 2, tu passes un pointeur en paramètre (c'est à dire un entier), tu modifies ce pointeur (c'est à dire la valeur du pointeur, ie: la valeur de l'entier), mais à aucun moment, tu n'as modifié l'objet originel.

    Si tu veux modifier l'objet originel, il faut donc que tu modifies la zone mémoire qui est à l'adresse que tu reçois en paramètre. (d'ou l'utilisation obligatoire de l'opérateur *)

  5. #5
    Membre régulier Avatar de Tex-Twil
    Inscrit en
    Avril 2004
    Messages
    447
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 447
    Points : 122
    Points
    122
    Par défaut
    oui je comprends. C'est vrai que c'est évident Il suffit de lire et bien comprendre. Donc c'est à cause de cette instruction que ce n'est pas possible: (normal car elle modifie la variable locale)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dh = DH_generate_parameters(PRIME_LEN, GENERATOR, NULL, NULL);
    Si par exemple le prototype avait éé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void DH_generate_parameters(int PRIME_LEN, int GENERATOR, DH *dh, ...);
    ça serait possible.

    Revenons à ta façon de faire
    Cala veut dire que je passe "l'adresse d'une adresse qui pointe vers DH", c ça ?
    et ensuite on modifie le contenu de cette adresse (donc l'adresse de DH):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *dh = DH_generate_parameters(PRIME_LEN, GENERATOR, NULL, NULL);
    Dans le prog appellant, on passe l'adresse du pointeur
    Ai-je bien compris ?

  6. #6
    Expert éminent
    Avatar de PRomu@ld
    Homme Profil pro
    Ingénieur de Recherche
    Inscrit en
    Avril 2005
    Messages
    4 155
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Ingénieur de Recherche
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2005
    Messages : 4 155
    Points : 6 486
    Points
    6 486
    Par défaut
    Si par exemple le prototype avait éé
    Code:

    void DH_generate_parameters(int PRIME_LEN, int GENERATOR, DH *dh, ...);

    ça serait possible.
    Tout dépend de la manière dont est utilisé le pointeur dh, si on modifie la valeur pointée à l'adresse dh alors OK, si la fonction modifie dh directement, c'est pas bon.

    Cala veut dire que je passe "l'adresse d'une adresse qui pointe vers DH", c ça ?
    Oui, si tu veux, mais ne t'arrête pas seulement aux termes.

    Dans le prog appellant, on passe l'adresse du pointeur
    Code:
    test(&dh)


    Ai-je bien compris ?
    Oui, tu as compris comment on utilisait, en fait, il faut que tu te dises, que tu rajoutes un "pointeur sur ..." en plus pour pouvoir modifier ce qui est pointé à cette adresse.

    En fait il faut te poser des questions lorsque tu as un pointeur en paramètre (ex *s) et que dans ta fonction tu modifies ce pointeur et pas ce qui y est pointé (ie s = ... au lieu de *s = ... )

    Lorsque ton type est déja un pointeur (un exemple courant est FILE* ), il faut utiliser la ruse (ce n'est pas une ruse en fait, mais j'aime bien le terme ) que je t'ai montré.

  7. #7
    Membre régulier Avatar de Tex-Twil
    Inscrit en
    Avril 2004
    Messages
    447
    Détails du profil
    Informations forums :
    Inscription : Avril 2004
    Messages : 447
    Points : 122
    Points
    122
    Par défaut
    ok merci

    résolu

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/03/2014, 23h10
  2. Réponses: 4
    Dernier message: 08/11/2012, 15h11
  3. paramètres pour une fonction
    Par bul dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 28/05/2005, 07h49
  4. Réponses: 9
    Dernier message: 13/05/2005, 03h13
  5. Passer en paramètre d'une fonction (...)
    Par Captain_JS dans le forum C++
    Réponses: 5
    Dernier message: 03/11/2004, 07h18

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