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 :

Manipulation de pointeur et structure dynamique


Sujet :

C

  1. #21
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Spootnik
    À mon avis, ce que tu trouves compliqué, c'est plutôt le fait que je passe d'abord par un pointeur void * avant d'assigner l'adresse pour ma table. Je pensais que c'était une bonne habitude à prendre : je me suis basé sur la façon par laquelle tu alloues la mémoire dans le programme Indenteur :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
         void *tmp = realloc (str1, len1 + strlen (str2) + 1);
     
         if (tmp != NULL)
         {
              strCat = tmp;
    Ah ? Il y a un realloc() dans ton code ? Je ne l'ai pas vu. Il ne faut pas recopier du code qu'on ne comprend pas et si on ne le comprends pas, il faut poser des questions, (surtout si l'auteur est à portée de main...)

    http://emmanuel-delahaye.developpez....tes.htm#malloc
    http://emmanuel-delahaye.developpez....es.htm#realloc

    Bien que dans la table ce soit avec malloc(), le principe est le même.
    Ben non. avec malloc() , c'est plus simple parce que allouer, c'est pas pareil que réallouer...
    De plus, je tiens à prévenir l'utilisateur en cas d'erreur, et non pas simplement renvoyer un pointeur NULL.
    Euh, tu peux justifier ? Parce que ça va à l'encontre de la pratique universellement reconnue qui veut que les fonctions de bas niveau (qui ne savent même pas ce qu'est un printf(), les pauvres...) soient évidemment "muettes" (sauf en mode debug, mais c'est autre chose), mais qu'elles retournent un code OK ou erreur (comme fopen(), malloc(), fgetc() etc.). Tu as déjà vu une fonction de bibliothèque pleurer sa mère parce qu'il y a une erreur ?)

    Au contraire, le code d'erreur est remonté au plus haut niveau (applicatif) et là, une décision intelligente et contextuelle est prise :
    • Ficher inconnu ? -> création ou proposition de création etc.
    • Pas assez de mémoire -> on recommence dans 1 seconde. Trop d'essais ? On sauvegarde et on quitte en prévenant gentiment l'utilisateur etc.

    Ce n'est pas à la bibliothèque de prendre ce genre de décision. Jamais.
    Cela pourrait donner quelquechose comme ça :
    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
     
    // creation de la Table
    Table *newTable(void)
    {
         // allocation de l espace necessaire
         Table *newTable = malloc(sizeof(Table));
     
         if (newTable != NULL)
         {
              // quelques mises au point une fois la memoire allouee
              newTable->count = 0;
              newTable->Items = NULL;
     
              return newTable;
         }
         else
         {
              puts("*** erreur: newTable(): memoire insuffisante\n");
              // retour NULL en cas de probleme lors de l allocation
              return NULL;
         }
    }
    Je ne trouve pas ce code compliqué.
    Ah ? Pourquoi 2 return ?. Et tu connais maintenant ma position sur les messages. En mode Debug, OK. Pas en Release. Pas besoin de noms compliqué. On a un pointeur, p suffit bien. Je te montre une méthode d'initialisation rapide et portable et auto évolutive :
    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
     
    // creation de la Table
    Table *newTable(void)
    {
         // allocation de l espace necessaire
         Table *p = malloc (sizeof *p);
     
         if (p != NULL)
         {
            /* mise a 0 automatique de tous les champs. */
             static const Table z = {0};
             *p = z;
         }
    #if DBG
         else
         {
              puts("*** erreur: newTable(): memoire insuffisante\n");
         }
    #endif
         return p;
    }
    NULL est défini par (en tout cas chez moi, mais je pense que c'est pareil chez tout le monde non ?) :
    Pas du tout. Tu devrais lire la norme plus souvent.

    http://emmanuel-delahaye.developpez.com/notes.htm#norme

    Sur le plan sémantique, NULL est équivalent à 0 dans le contexte d'un pointeur, mais il peut être implémenté au moins de 2 façons :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define NULL 0
    #define NULL ((void*)0)
    et j'ai déjà vu ceci
    alors se garder de toute hypothèses, et ne pas utiliser les éléments du langage hors de leur contexte.

    Pour un caractère, c'est 0 ou '\0' si tu veux te la péter.
    Donc renvoyer NULL ou 0 revient au même (si les définitions sont les mêmes sur tous les systèmes). Je me trompe ?
    Tu te trompes et mon compilateur s'en est aperçu.
    Tu parles des apostrophes et des quelques caractères accentués c'est ça ?
    Oui. Pour rester portable, se limiter au charset officiel :

    http://emmanuel-delahaye.developpez....htm#caracteres
    Pas de Wi-Fi à la maison : CPL

  2. #22
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par souviron34
    Donc si c'est un int, il faut initialiser avec un int, et '0' est un int.
    Mais '0' ne vaut pas 0 !
    Pas de Wi-Fi à la maison : CPL

  3. #23
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    non bien sûr Emmanuel, mais je mettais les guillemets par pour un caractère, mais pour mettre l'emphase.. Oui j"aurais dû mettre en gras
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  4. #24
    Membre expérimenté Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Points : 1 312
    Points
    1 312
    Par défaut
    Bon bah je préfère virer directement tous les messages d'erreur, je n'aime pas avoir deux versions dans mes sources.

    Et pour les malloc() et realloc(), je fais le ménage et je poste ce que j'ai obtenu.

    Merci pour votre aide

  5. #25
    Membre expérimenté Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Points : 1 312
    Points
    1 312
    Par défaut
    J'ai une question à propos de malloc(). Je suis presque sûr de la réponse mais j'aimerais tout de même avoir une confirmation.

    Lorsque je créé un structure qui doit contenir un composant dont la taille n'est pas toujours la même :
    - je suis censé laisser le compilateur s'occuper d'allouer l'espace nécessaire à la structure, puis allouer moi-même ensuite l'espace pour l'objet de taille connue seulement à l'exécution ?
    - ou allouer manuellement et directement la structure avec l'espace nécessaire ?

    D'après moi, c'est la 1ere possibilité, mais j'ai peur d'allouer de la mémoire qui ne sera pas utilisée. Je ne tiens pas à avoir des zones de mémoires allouées mais vides. Avec la 2e méthode je suis sûr de ne pas avoir de mémoire allouée et vide, mais je ne pense pas qu'elle soit correcte.

    Un exemple selon les deux méthodes :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    // petit rappel
    typedef struct{
    	int id;
    	char *content;
    } Item;

    1ere méthode
    Code C : 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
    Item *newItemFromString(char const *string)
    {
         if (string == NULL)
              return NULL;
         
         Item *newItem = malloc(sizeof(Item));
         
         if (newItem != NULL)
         {
              newItem->id = 0;
              newItem->content = malloc(sizeof(char) * (strlen(string) + 1));
              if (newItem->content != NULL)
              {
                   strcat(newItem->content, string);
              }
              return newItem;
         }
         return NULL;
    }

    2e méthode
    Code C : 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
    Item *newItemFromString(char const *string)
    {
         if (string == NULL)
              return NULL;
         
         Item *newItem = malloc(sizeof(int) + sizeof(char) * (strlen(string) + 1));
         
         if (newItem != NULL)
         {
              newItem->id = 0;
              if (newItem->content != NULL)
              {
                   strcat(newItem->content, string);
              }
              return newItem;
         }
         return NULL;
    }

    Merci

  6. #26
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    euh ..

    C'est le contraire non ?

    Ta deuxième méthode est celle que je prendrais....

    1) dans la première tu alloues une place mémoire, nous sommes d'accord. Mais tu n'affectes pas le pointeur content.... Donc ton strcat après va crasher.... Et de plus, même si tu l'affectais, c'est franchement pas une manière de faire.

    2) je ne voit pas en quoi cela dépend de l'éxécution ou non....
    Dans les 2 cas tu as 1 string et tu fais strlen() pour calculer la taille...
    Je ne vois vraiment pas comment tu pourrais avoir des éléments alloués mais vides, comme tu dis...

    3) faire strcat() suppose que tu as déjà une chaine dedans, ou que le premier caractère est NULL. Dans ce cas le mieux est strcpy()......
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  7. #27
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par souviron34
    3) faire strcat() suppose que tu as déjà une chaine dedans, ou que le premier caractère est NULL.<...>
    NUL ou null ou 0 ou '\0'. J'ai eu du mal à lui faire comprendre que NULL != 0...

    http://www.developpez.net/forums/sho...3&postcount=21
    Pas de Wi-Fi à la maison : CPL

  8. #28
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    ooppsss autant pour moi
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  9. #29
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par souviron34
    ooppsss autant pour moi
    "au temps"... mais c'est un autre débat...
    Pas de Wi-Fi à la maison : CPL

  10. #30
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    euhhh .. Non pas dans ce cas... C'est vraiment "autant"....
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  11. #31
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Spootnik

    Un exemple selon les deux méthodes :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    // petit rappel
    typedef struct{
    	int id;
    	char *content;
    } Item;

    1ere méthode
    Code C : 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
    Item *newItemFromString(char const *string)
    {
         if (string == NULL)
              return NULL;
         
         Item *newItem = malloc(sizeof(Item));
         
         if (newItem != NULL)
         {
              newItem->id = 0;
              newItem->content = malloc(sizeof(char) * (strlen(string) + 1));
              if (newItem->content != NULL)
              {
                   strcat(newItem->content, string);
              }
              return newItem;
         }
         return NULL;
    }

    2e méthode
    Code C : 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
    Item *newItemFromString(char const *string)
    {
         if (string == NULL)
              return NULL;
         
         Item *newItem = malloc(sizeof(int) + sizeof(char) * (strlen(string) + 1));
         
         if (newItem != NULL)
         {
              newItem->id = 0;
              if (newItem->content != NULL)
              {
                   strcat(newItem->content, string);
              }
              return newItem;
         }
         return NULL;
    }

    Merci
    Ta 2ème méthode est à oublier. Elle ne fait pas du tout ce que tu penses. Ton utilisation de malloc fait des supposition sur les contraintes d'alignement d'un int et d'un pointeur, et tu confonds tableau de caractère est pointeur sur char. La ligne suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Item *newItem = malloc(sizeof(int) + sizeof(char) * (strlen(string) + 1));
    n'est donc pas correcte.

    Personnellement, j'utiliserais la 1ère version avec quelques modifications stylistiques. De plus, si je ne trompe pas, les identificateurs qui commencent par str comme string sont réservés:
    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
    Item *newItemFromString(char const *s_string)
    {
        Item *p_returnVal = NULL;
     
        if (s_string != NULL)
        {
            Item *p_newItem = malloc(sizeof *p_newItem);
            if (p_newItem != NULL)
            {
                p_newItem->id = 0;
                p_newItem->content = malloc((strlen(s_string) + 1) 
                        * sizeof *p_newItem->content);
                if (p_newItem->content != NULL)
                {
                    p_newItem->content[0] = '\0';
                    strcat(p_newItem->content, s_string); 
                    p_returnVal = p_newItem;
                }
                else 
                {
                    free(p_newItem), p_newItem = NULL;
                } 
            }
        }
     
        return p_returnVal;
    }
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  12. #32
    Membre expérimenté Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Points : 1 312
    Points
    1 312
    Par défaut
    Citation Envoyé par mujigka
    De plus, si je ne trompe pas, les identificateurs qui commencent par str comme string sont réservés:
    [...]
    Thierry
    Les identificateurs commençant par str sont réservés ? je n'avais encore jamais vu ça... tu peux me dire quelles sont tes sources ?

    Sinon je trouve que tu fais bien compliqué pour pas grand chose.
    Citation Envoyé par mujigka
    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
    Item *newItemFromString(char const *s_string)
    {
        Item *p_returnVal = NULL;
     
        if (s_string != NULL)
        {
            Item *p_newItem = malloc(sizeof *p_newItem);
            if (p_newItem != NULL)
            {
                p_newItem->id = 0;
                p_newItem->content = malloc((strlen(s_string) + 1) 
                        * sizeof *p_newItem->content);
                if (p_newItem->content != NULL)
                {
                    p_newItem->content[0] = '\0';
                    strcat(p_newItem->content, s_string); 
                    p_returnVal = p_newItem;
                }
                else 
                {
                    free(p_newItem), p_newItem = NULL;
                } 
            }
        }
     
        return p_returnVal;
    }
    Personnellement je n'aime pas trop les variables composées de '_', mais bon ce n'est pas ce qu'il y a de plus important.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    p_newItem->content[0] = '\0';
    Je ne vois pas à quoi ça sert. Tu peux me dire ? d'autant plus que commencer une chaîne de caractère par un '\0', ça pause beaucoup de problèmes (calcul avec strlen(), affichage avec printf()...). Non, décidément je ne comprend pas pourquoi tu as mis ça là.

    Et deux pointeurs pour le prix d'un (p_newItem, p_returnVal), à quoi bon ? puisqu'un malloc() qui échoue renvoie NULL non ? donc ça revient au même...

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    sizeof *p_newItem->content
    Pour l'instant je ne prévois pas de modifier le type de ma variable content, donc autant faire simple : sizeof(char).

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    /* ... */
                    p_returnVal = p_newItem;
                }
                else 
                {
                    free(p_newItem), p_newItem = NULL;
                }

    Si je ne m'abuse, lorsque tu appelles free(), tu libère l'adresse mémoire désignée par p_newItem, or tu as assigné cette adresse à p_returnVal, donc du coup, cette même adresse se retrouve vide, et p_returnVal pointe dans le vide non ? Même si tu ne passe que p_newItem à free(), l'adresse mémoire libérée est la même.

    Merci tout de même pour ta réponse

  13. #33
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Spootnik
    Les identificateurs commençant par str sont réservés ? je n'avais encore jamais vu ça... tu peux me dire quelles sont tes sources ?
    Des sources officielles, il n'y en a qu'une, c'est la norme...

    http://emmanuel-delahaye.developpez.com/notes.htm#norme

    Mais j'ai fait un résumé

    http://emmanuel-delahaye.developpez....htm#id_reserve
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    p_newItem->content[0] = '\0';
    Je ne vois pas à quoi ça sert. Tu peux me dire ? d'autant plus que commencer une chaîne de caractère par un '\0', ça pause beaucoup de problèmes (calcul avec strlen(), affichage avec printf()...). Non, décidément je ne comprend pas pourquoi tu as mis ça là.
    Quels genre de problèmes ça pourrait bien poser d'initialiser une chaine de caractères à 'chaine vide'. ("")
    C'est pareil que :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    strcpy (p_newItem->content, "");
    si tu préfères.
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    sizeof *p_newItem->content
    Pour l'instant je ne prévois pas de modifier le type de ma variable content, donc autant faire simple : sizeof(char).
    Justement l'intérêt de ne pas mettre le type mais le pointeur est d'anticiper les évolutions de manière automatique. Enfin, tu fais ce que veux...

    D'autre part je rappelle que sizeof(char) est certes, une manière simple d'écrire (sizeof (char) * 2) / 2, mais que c'est une manière compliquée d'écrire 1.
    Pas de Wi-Fi à la maison : CPL

  14. #34
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Spootnik
    Les identificateurs commençant par str sont réservés ? je n'avais encore jamais vu ça... tu peux me dire quelles sont tes sources ?
    Tiré de "C Unleashed" chapitre 2 publié par Sams publishing en 2000 (une référence qui compte pour beaucoup de programnmeurs C), article écrit par Richard Heathfield, émminent intervenant sur comp.lang.c:
    Code C Unleashed : 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
    The ANSI committee recognizes thant languages grow or die ... 
    ...For example, anything beginning with "str" is reserved because, although
     there are plenty of standard library functions beginning with "str", there is 
    certainly much more useful functionality that could be provided for 
    string-handling. To allow for this, the letter combination "str" is reserved, The
     same applies to "is" and "to" (to allow <ctype.h> to be extended), "mem" (for
     extra manipulation functions, "SIG" (for new signals) and a number of other 
    prefixes.
    
    ... don't use these identifiers:
    E[0-9]*
    LC[A-Z]*
    Offsetof
    str[a-z]*
    _*  (on ne devrait pas utiliser de nom commençant par underscore!)
    E[A-Z]*
    mem[a-z]*
    raise
    to[a-z]*
    is[a-z]*
    NDEBUG
    SIG[A-Z]*
    wcs[a-z]*

    Enfin, c'est la norme du langage C qui aura le dernier mot, mais je doute que Richard Heathfield se soit aventuré à écrire cela sans s'appuyer sur la norme. (j'ai vérifié, fais-moi confience, string est bien un identificateur réservé)

    Citation Envoyé par Spootnik
    Personnellement je n'aime pas trop les variables composées de '_', mais bon ce n'est pas ce qu'il y a de plus important.

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    p_newItem->content[0] = '\0';
    Je ne vois pas à quoi ça sert. Tu peux me dire ? d'autant plus que commencer une chaîne de caractère par un '\0', ça pause beaucoup de problèmes (calcul avec strlen(), affichage avec printf()...). Non, décidément je ne comprend pas pourquoi tu as mis ça là.
    Selon la spécification de la bibliothèque standard du C e.g je cite ici "La bibliothèque C standard de P.J Plauger chez Masson/Prentice Hall 1995, chapitre 14 p417:
    Citation Envoyé par Plauger
    strcat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    #include <string.h>
    char *strcat(char *s1, const char *s2);
    La fonction strcat ajoute une copie de la chaîne pointée par s2 (y compris le caractère nul de la fin) à la fin de la chaîne pointée par s1, Le premier caractère de s2 écrase le caractère nul de fin de s1
    Si la chaîne pointée par s1 ne contient pas de caractère nul (dans ton code, newItem->content n'est pas initialisé), comment strcat sait-elle où commencer à copier? Tu aurais aussi bien pu utiliser strcpy() ici.

    Citation Envoyé par Spootnik
    Et deux pointeurs pour le prix d'un (p_newItem, p_returnVal), à quoi bon ? puisqu'un malloc() qui échoue renvoie NULL non ? donc ça revient au même...
    Pour moi, une fonction ne possède qu'un point d'entrée et qu'un point de sortie i.e. une seule instruction return par fonction.

    Citation Envoyé par Spootnik
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    sizeof *p_newItem->content
    Pour l'instant je ne prévois pas de modifier le type de ma variable content, donc autant faire simple : sizeof(char).
    Si tu veux faire simple, pourquoi ne pas omettre sizeof(char) qui vaut 1 par définition? Ma manière de faire facilite la maintenance et l'évolution du code.
    Citation Envoyé par Spootnik
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    /* ... */
                    p_returnVal = p_newItem;
                }
                else 
                {
                    free(p_newItem), p_newItem = NULL;
                }
    Si je ne m'abuse, lorsque tu appelles free(), tu libère l'adresse mémoire désignée par p_newItem, or tu as assigné cette adresse à p_returnVal, donc du coup, cette même adresse se retrouve vide, et p_returnVal pointe dans le vide non ? Même si tu ne passe que p_newItem à free(), l'adresse mémoire libérée est la même.$
    Ben oui, si je ne peux pas allouer la mémoire pour p_newItem->content, je libère p_newItem et quiite la fonction. Si tu quitte la fonction en renvoyant NULL, la création d'un nouvel objet Item ayant échoué. Non?

    Citation Envoyé par Spootnik
    Merci tout de même pour ta réponse
    Je t'en prie

    Meilleures salutations

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  15. #35
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par mujigka
    Personnellement, j'utiliserais la 1ère version avec quelques modifications stylistiques.
    La structure basique d'un constructeur est la suivante :

    (Meta-C)
    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
     
    T *create (<params>)
    {
       T *this = NULL;
     
       /* test de la validite des parametres */
       if (<params OK>)
       {
          this = malloc (sizeof *this);
          if (this != NULL)
          {
             static const T z = {0};
             *this = z;
     
             /* suite de la construction... */
          }
       }
       return this;
    }
    Appliqué ici, ça donne :
    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
     
    Item *create (char const *s)
    {
       Item *this = NULL;
     
       /* test de la validite des parametres */
       if (s != NULL)
       {
          this = malloc (sizeof *this);
          if (this != NULL)
          {
             static const Item z = { 0 };
             *this = z;
     
             /* suite de la construction... */
             this->id = 0;
             this->content = strdup (s);
             if (this->content == NULL)
             {
                free (this), this = NULL;
             }
          }
       }
       return this;
    }
    Rappel strdup() n'est pas standard C mais POSIX.1, donc très portable (et facile à reproduire).
    Pas de Wi-Fi à la maison : CPL

  16. #36
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    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
     
    Item *create (char const *s)
    {
       Item *this = NULL;
     
       /* test de la validite des parametres */
       if (s != NULL)
       {
          this = malloc (sizeof *this);
          if (this != NULL)
          {
             static const Item z = { 0 };
             *this = z;
     
             /* suite de la construction... */
             this->id = 0;
             this->content = strdup (s);
             if (this->content == NULL)
             {
                free (this), this = NULL;
             }
          }
       }
       return this;
    }
    Merci Emmanuel pour ta manière de faire très élégante. L'utilisation d'une variable statique et de strdup() rend le code très lisible. Je ne pense jamais à utiliser ces outils.

    Salutations

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  17. #37
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Spootnik
    Et deux pointeurs pour le prix d'un (p_newItem, p_returnVal), à quoi bon ? puisqu'un malloc() qui échoue renvoie NULL non ? donc ça revient au même...
    J'utilise une variable returnVal de manière idiomatique afin de me faciliter les traitements d'erreur tout en conservant un seul point de sortie à ma fonction. Mais ici, ce n'est pas utile, tu as raison sur ce point.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  18. #38
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    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
     
    Item *create (char const *s)
    {
       Item *this = NULL;
     
       /* test de la validite des parametres */
       if (s != NULL)
       {
          this = malloc (sizeof *this);
          if (this != NULL)
          {
             static const Item z = { 0 };
             *this = z;
     
             /* suite de la construction... */
             this->id = 0;
             this->content = strdup (s);
             if (this->content == NULL)
             {
                free (this), this = NULL;
             }
          }
       }
       return this;
    }
    A quoi sert la ligne:
    Ce champ a déjà été initialisé à zéro avec:
    Non?

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  19. #39
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par mujigka
    A quoi sert la ligne:
    Ce champ a déjà été initialisé à zéro avec:
    Non?
    C'est redondant, certes, mais si une initiation explicite a été demande, je la laisse...

    Disons qu'il y a 2 niveaux.

    est brutal, efficace, sans discernement mais auto-démerdant (notamment en cas d'ajout d'élément dans la structure, on part sur des bases connues : 0, NULL, "", 0.0, 0.0f etc.).

    ensuite vient le réglage fin...

    etc.

    Oui, il peut y avoir redondance, et le compilateur ne fera sans doute pas l'optimisation...

    Si nécessaire, on peut retirer le code inutile.
    Pas de Wi-Fi à la maison : CPL

  20. #40
    Membre expérimenté Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Points : 1 312
    Points
    1 312
    Par défaut
    Merci pour vos réponses .
    Un petit détail :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    static const Item z = { 0 };
    *newItem = z;

    Je ne comprend pas bien comment ça fonctionne. Pourquoi une liste { 0 } ? et pourquoi passer par là pour tout mettre à zéro ? je crois que je préfère la méthode fine ...

    Je poste aussi les nouvelles sources. J'ai encore des doutes sur ce que j'ai mis. Je n'ai pas réussi à utiliser ton outil SYSALLOC Emmanuel : lorsque je le compile avec mes sources, j'ai plein d'erreurs même sur des lignes juste composées de commentaires, donc pour l'instant, nada.

    Edit: le log d'erreur est aussi joint.
    Fichiers attachés Fichiers attachés

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 4 PremièrePremière 1234 DernièreDernière

Discussions similaires

  1. Manipulation de pointeur sur tableau dynamique
    Par vincenet dans le forum Débuter
    Réponses: 12
    Dernier message: 09/12/2014, 17h53
  2. Réponses: 11
    Dernier message: 01/08/2010, 14h34
  3. [C++ .NET] Structure dynamique
    Par tidou dans le forum VC++ .NET
    Réponses: 17
    Dernier message: 29/10/2004, 20h08
  4. Réponses: 12
    Dernier message: 26/04/2004, 08h32
  5. probleme avec pointeurs de structures
    Par remi77 dans le forum C
    Réponses: 2
    Dernier message: 20/10/2003, 13h19

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