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

  1. #1
    Membre du Club
    Homme Profil pro
    Apprenti Ingénieur Informatique
    Inscrit en
    octobre 2015
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Apprenti Ingénieur Informatique
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2015
    Messages : 63
    Points : 64
    Points
    64

    Par défaut Malloc sur pointeur de structure

    Bonjour à tous.

    Je suis développeur de base windev, et je me lance dans le C qui est plus prêt de ce qui se passe côté machine.

    Je suis en train de suivre un cours et je voudrais réaliser un pendu (classique).

    Je voudrais donc essayer de faire au plus propre possible en utilisant des malloc et des struct

    voici donc mon code :
    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
     
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    typedef struct Test Test;
    struct Test
    {
    	int coupsRestants;
      int taille;
    	char *motSecret;
      char *motCache;
    };
     
    void allocationCHaine(char *tempChar){
      tempChar = malloc(6 * sizeof(char));
     
    	tempChar[0] = 'S';
    	tempChar[1] = 'A';
    	tempChar[2] = 'L';
    	tempChar[3] = 'U';
    	tempChar[4] = 'T';
    	tempChar[5] = '\0';
     
    	printf("tempChar : %s\n",tempChar);
    }
     
    void initStruct(Test *tempTest){
      tempTest->taille = 0;
    	tempTest->coupsRestants = 0;
    	tempTest->motSecret = NULL;
    	tempTest->motCache = NULL;
    	allocationCHaine(tempTest->motSecret);
    }
     
    int main(int argc, char const *argv[])
    {
    	Test mainStruct;
    	initStruct(&mainStruct);
     
    	printf("mainStruct.motSecret : %s\n",mainStruct.motSecret);
    	return 0;
    }
    Résultats :
    tempChar : SALUT
    mainStruct.motSecret : (null)

    Je tiens à préciser que chez moi ces fonctions sont dans différents fichiers mais je voulais simplifier, le principe est le même
    Je cherche donc à affecter ma chaine directement avec un malloc plutôt qu'un tableau fixe.
    Le problème ici c'est que forcément on ne modifie pas la chaine de la structure.

    Je suis donc dans la logique tenté de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    void allocationCHaine(char *tempChar){
      *tempChar = malloc(6 * sizeof(char));
     
    	*tempChar[0] = 'S';
    	*tempChar[1] = 'A';
    	*tempChar[2] = 'L';
    	*tempChar[3] = 'U';
    	*tempChar[4] = 'T';
    	*tempChar[5] = '\0';
     
    	printf("tempChar : %s\n",tempChar);
    }
    Sauf que là, ça ne compile pas.

    Pouvez-vous un peu m’éclairer sur tous ces principes et sur la solution à adopter ?

    Brody

  2. #2
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    2 972
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 2 972
    Points : 6 602
    Points
    6 602

    Par défaut

    C'est le truc ultra classique

    Pour simplifier tous les passages de paramètres en C sont par valeur.
    Donc on passe des pointeurs pour modifier cette valeur.
    Mais lorsqu'on passe un pointeur, c'est également un passage par valeur de l'adresse (c'est un entier de 32 ou 64 bits).

    Or dans ton cas, tu veux également modifier cette adresse. La solution c'est soit un double pointeur soit un retour pointeur.

    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
    54
    55
    56
    void create_string01(char** str){
       if (str != NULL) {
            (*str) = malloc(6 /** sizeof(char)*/);
     
            if ((*str) != NULL) {
    /*          maybe use strcpy */
                *(*str)     = 'S';
                *(*str + 1) = 'A';
                *(*str + 2) = 'L';
                *(*str + 3) = 'U';
                *(*str + 4) = 'T';
                *(*str + 5) = '\0';
     
                printf("create_string01 - debug : %s\n", (*str));
            }
        }
    }
     
     
    char* create_string02(void){
        char* str;
     
        str = malloc(6 /** sizeof(char)*/);
     
        if (str != NULL) {
    /*      maybe use strcpy */
            str[0] = 'S';
            str[1] = 'A';
            str[2] = 'L';
            str[3] = 'U';
            str[4] = 'T';
            str[5] = '\0';
     
            printf("create_string02 - debug : %s\n", str);
        }
     
        return str;
    }
     
     
     
    /* ... */
     
    char* tab1;
    char* tab2;
     
    tab1 = NULL;
    create_string01(&tab1);
     
    tab2 = create_string02();
     
     
    /* ... */
     
    free(tab1);
    free(tab2);

  3. #3
    Rédacteur
    Avatar de dvsoft
    Homme Profil pro
    Architecte technique
    Inscrit en
    août 2002
    Messages
    175
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : août 2002
    Messages : 175
    Points : 614
    Points
    614

    Par défaut juste pour rigoler

    Brody travaille à coté de moi

    voila ma solution, je n'ai pas fait de C depuis la nuit des temps.

    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
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    struct Test
    {
    	int coupsRestants;
    	int taille;
    	char *motSecret;
      	char *motCache;
    };
    typedef struct Test Test;
     
    void GetWordExt(char** Value)
    {
    	*(Value) = (char*)malloc(32);
    	strcpy(*Value,"SALUT");
    }
     
    void initStruct(Test *tempTest)
    {
       	tempTest->taille       = 0;
     	tempTest->coupsRestants= 0;
    	GetWordExt(&tempTest->motSecret);
    }
     
    int main(int argc, char *argv[])
    {
    	Test* mainStruct = malloc(sizeof(Test));
    	initStruct(mainStruct);
     
    	printf("mainStruct.motSecret : %s\n",mainStruct->motSecret);
    	return 0;
    }

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    946
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 946
    Points : 4 829
    Points
    4 829

    Par défaut

    Bonjour,

    Ça ne compile pas. En effet quand on écrit : char * tempChar, ça veut dire "pointeur sur char <=> tempChar", on peut aussi le lire "char <=> *tempChar".
    Donc ligne 16, tu veux mettre le pointeur dans *tempChar qui est un char (il sera un peu beaucoup à l'étroit!)
    Donc lignes 18 à 23, tempChar[x] est un char, et c'est devant les pointeurs que l'on met une étoile pour les déréférencer, ici * devant un char n'a pas de sens.

    Pour commencer et limiter l'utilisation des pointeurs (pour éviter les pointeurs de pointeurs) on peut changer le format de ta fonction. Elle ne va rien recevoir mais retourner le pointeur alloué. Ça devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    char *allocationCHaine(void) {
    	char* tempChar = malloc( 6 ); // allocation de 6 char, le pointeur est mémorisé dans le pointeur sur des char appelé tempChar
     
    	tempChar[0] = 'S';   // le premier char pointé par tempChar reçoit le char 'S'.
    	tempChar[1] = 'A';   // le second char pointé par tempChar reçoit le char 'A'.
    	tempChar[2] = 'L';
    	tempChar[3] = 'U';
    	tempChar[4] = 'T';
    	tempChar[5] = '\0';
     
    	printf("tempChar : %s\n",tempChar);
     
    	return  tempChar;
    }

  5. #5
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    2 972
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 2 972
    Points : 6 602
    Points
    6 602

    Par défaut

    Tout le monde a oublié de dire que le type char est le seul type qui a une taille fixé par la norme (donc quelque soit la plateforme) : c'est pour cela que sizeof(char) vaut 1 et peut être oublié (moi je le mets en commentaire )
    Parce que @dvsoft nous fait un malloc(32) à la hussarde

    Et vos codes sont quand même grades

    Personne teste le retour du malloc : c'est vrai osef, on a tous 8 gigas de mémoire.
    Personne libère la mémoire avec free : c'est vrai osef, à la fermeture du programme, la mémoire est supprimée.

    Sans parler qu'en C, on a pas besoin de caster le retour du malloc.

  6. #6
    Membre du Club
    Homme Profil pro
    Apprenti Ingénieur Informatique
    Inscrit en
    octobre 2015
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Apprenti Ingénieur Informatique
    Secteur : Industrie

    Informations forums :
    Inscription : octobre 2015
    Messages : 63
    Points : 64
    Points
    64

    Par défaut

    Bonjour à tous,

    Merci pour vos réponses qui fonctionnent.

    Je ne voulais pas utiliser le return car je voulais surtout pratiquer les pointeurs.

    Je vais donc analyser tout ça et bien reprendre le principe de pointeur de pointeur

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 343
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 7 343
    Points : 20 904
    Points
    20 904
    Billets dans le blog
    1

    Par défaut

    Bonjour
    Citation Envoyé par brody Voir le message
    Je vais donc analyser tout ça et bien reprendre le principe de pointeur de pointeur
    En fait, c'est l'application brute du principe "toute fonction qui veut modifier une variable extérieure (à elle) doit recevoir l'adresse de cette variable.
    Une fonction veut modifier un int ? elle recevra l'adresse de cet int qu'elle stockera dans un int étoile. Puis tous les accès à cette variable se feront au travers du pointé
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void init(int *pt, int v) {
    	(*pt)=v;
    }
     
    int main() {
    	int v;
    	init(&v, 100);
    }

    Même exemple avec un float qui sera alors modifié via un float étoile
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void init(float *pt, float v) {
    	(*pt)=v;
    }
     
    int main() {
    	float v;
    	init(&v, 100.0);
    }
    Donc on voit bien ici le principe général où si une fonction doit modifier un "truc", elle recevra alors l'adresse de ce truc qu'elle stockera dans un "truc étoile".

    Si on l'applique maintenant à une fonction qui doit modifier un "char étoile", alors le mécanisme reste exactement le même: elle recevra l'adresse de ce "char étoile" qu'elle stockera dans un "char étoile étoile"
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void init(char **pt, int v) {
    	(*pt)=malloc(v * sizeof(**pt));	// Désolé foetus, je préfère mettre le sizeof pour des raisons d'esthétique et de portabilité ;)
    	strcpy(*pt, "Salut");
    }
     
    int main() {
    	char *chaine;
    	init(&chaine, 6);
    }
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 05/08/2009, 09h23
  2. Petit problème sur pointeurs de structures
    Par benjaminb dans le forum C
    Réponses: 5
    Dernier message: 05/01/2008, 20h08
  3. pointeur sur Tableaux de structures
    Par Linu6 dans le forum C
    Réponses: 10
    Dernier message: 31/12/2007, 14h29
  4. Réponses: 2
    Dernier message: 16/09/2007, 19h34
  5. question sur pointeur retourné par malloc()
    Par gauguin dans le forum C
    Réponses: 8
    Dernier message: 21/02/2007, 18h34

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