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 structure incluant char *


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 121
    Par défaut Pointeur de structure incluant char *
    Bonjour,

    J'essaie de modifier un caractère d'une chaîne de caractères dans une structure manipulée par un pointeur.

    Si on prend par exemple une structure qui inclut une chaîne de caractère dans sa définition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    typedef struct{
      int annee;
      char *marque;
    }Voiture;
    Si plus loin je créé un pointeur de Voiture v. Je peux initialiser la Voiture pointée par v de plusieurs façons :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Voiture *v = (Voiture *)malloc(sizeof(Voiture));
    v->marque = "Skoda";
    (*v).marque = "BMV";
    Mais si je veux modifier le 3ème caractère du champ marque, j'obtiens systématiquement un segfault ou une erreur avec l'une ou l'autre de ces solutions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    (*v).marque[2] = 'W'; //segmentation fault
    v->marque[2] = 'W'; //segmentation fault
    v->(marque + 2) = 'W'; //erreur
    // etc...
    Je pourrais bien sûr réinitialiser le champ en entier mais j'aimerais vraiment comprendre comment faire. Quelqu'un aurait une idée?

    Merci.

  2. #2
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    salut,

    ce n'est pas bon, tu dois faire un malloc pour la structure puis un malloc pour le char *.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Voiture *v = (Voiture *)malloc(sizeof(Voiture));
    v->marque = (char *)malloc(5*sizeof(char));
    et après tu fais un strcpy !!! pas de v->marque = "Skoda";

    cette ligne sera bonne après :
    v->marque[2] = 'W'; //segmentation fault

  3. #3
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    Attention, lors de l'allocation de la chaine de caractère, il faut penser à stocker le '\0' final :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    const char modele[] = "Skoda";
     
    Voiture *v = malloc(sizeof(Voiture));
    v->marque = malloc(strlen(modele) + 1);
    strcpy(v->marque, modele);
    Ou mieux, si la fonction est strdup disponible :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    const char modele[] = "Skoda";
     
    Voiture *v = malloc(sizeof(Voiture));
    v->marque = stdrup(modele);
    Et dans les deux cas, une fois qu'on a fini d'utiliser les structures :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    free(v->marque);
    free(v);

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 121
    Par défaut
    Merci pour vos réponses ça fonctionne mieux!

    Mais je ne comprends pas vraiment pourquoi ça ne pouvait pas marcher.
    J'ai déjà vu des exemples où des chaines de caractères sont initialisées directement sans malloc?

    Dans mon exemple je me disais que j'avais la structure dans le tas et la chaîne de caractère marque dans la pile. Bon ça me paraissait un peu bizarre mais ça passait à l'exécution... Où est-ce que je me trompe??

  5. #5
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    Citation Envoyé par barnoufal Voir le message
    J'ai déjà vu des exemples où des chaines de caractères sont initialisées directement sans malloc?
    es-tu capable de retrouver un exemple ?
    A mon avis, ce n'était pas un char *.

    char* est un pointeur, donc une adresse.
    je ne sais pas quelle est ta formation. Pour ma part, à l'école, les profs nous faisaient de belles représentations de l'espace mémoire pour bien comprendre les pointeurs.

  6. #6
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par barnoufal Voir le message
    J'ai déjà vu des exemples où des chaines de caractères sont initialisées directement sans malloc?
    On peut utiliser des chaines de caractères statiques (des tableaux) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    /* création d'une chaine de 14 caractères */
    char chaine[] = "toto est beau";
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    /* création d'une chaine de 6 caractères */
    char chaine[6];
    strcpy(chaine, "Hello");
    Après, quand tu parles de chaines sans utiliser de malloc[1], tu penses peut-être aux objets string qui appartiennent au c++.

    [1] ni realloc, ni calloc, ni strdup

    EDIT :

    En bonus, un peu de lecture sur les pointeurs : http://emmanuel-delahaye.developpez....age=Page5#LXXI
    Dernière modification par Deepin ; 26/07/2011 à 10h37.

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 121
    Par défaut
    J'ai vu des choses comme ce qu'a écrit Mabu et des trucs comme ci dessous. Cet exemple vient du site qu'il m'a conseillé (merci!). Il n'y a pas de malloc avant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char const *pf = "hello";

  8. #8
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par barnoufal Voir le message
    J'ai vu des choses comme ce qu'a écrit Mabu et des trucs comme ci dessous. Cet exemple vient du site qu'il m'a conseillé (merci!). Il n'y a pas de malloc avant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char const *pf = "hello";
    En effet, il n'y a pas de malloc... mais il y a un const. pf n'est donc pas modifiable. Je ne pense donc pas que cela réponde à ton besoin.

  9. #9
    Expert confirmé
    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
    Par défaut
    Citation Envoyé par mabu Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char const *pf = "hello";
    En effet, il n'y a pas de malloc... mais il y a un const. pf n'est donc pas modifiable. Je ne pense donc pas que cela réponde à ton besoin.
    pf est modifiable.
    Ce sont les éléments de la chaine "hello" qui sont déclarés, à juste titre, comme const donc non modifiables.
    Dans cette écriture, pf n'est pas un tableau de caractères contenant "hello", c'est un pointeur contenant l'adresse du début d'un tableau (situé ailleurs) non modifiable contenant la chaine "hello".
    Il est possible d'écrire pf =... mais pas pf[0]=...


    Dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char const pf[] = "hello";
    pf est un tableau d'éléments non modifiables, initialisé par la chaine "hello". Il n'est pas possible d'écrire pf = ... (pf est un tableau) ni pf[0] = ... (éléments non modifiables)

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 121
    Par défaut
    Désolé je persiste mais c'est ce genre d'exemple qui me fait me poser des questions...
    J'ai peu d'expérience en C mais je comprends l'allocation explicite de mémoire et la manipulation de pointeurs. Dans mon exemple du début du thread je voulais justement tester différentes façons de manipulation de chaînes de caractères. Je voulais aussi voir si on pouvait combiner l'allocation automatique dans la pile et l'allocation dynamique dans le tas au sein d'une structure.

    Quelque chose comme ceci fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     char *chaine = "Bonjour\0";
     printf("%s \n", chaine);
    Evidemment c'est étrange, mais au fond pas beaucoup plus que cette autre facilité d'écriture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     char chaine2[] = "Au revoir\0";
    En revanche ceci ne fonctionne pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char *chaine = "Bonjour\0";
    char chaine2[] = "Au revoir\0";
    printf("%s \n", chaine);
    *(chaine+1) = 'z'; //segmentation fault
    chaine2[1] = 'i'; //OK
    Je veux juste comprendre ce qui se passe pour chaine. A priori, comme pour chaine2, la valeur pointée par chaine est stockée dans un contexte de la pile puisqu'il n'y a ni malloc, calloc ou autre. Est-ce que le fait que je ne puisse pas accéder au contenu de l'adresse par une indirection sur le pointeur chaine est dû au fait qu'on ne peut accéder explicitement aux adresses mémoires de la pile?

  11. #11
    Expert confirmé
    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
    Par défaut
    A priori, comme pour chaine2, la valeur pointée par chaine est stockée dans un contexte de la pile puisqu'il n'y a ni malloc, calloc ou autre.
    Justement non!
    je répète ce que j'ai dit précédemment : chaine n'est pas un tableau, mais un pointeur qui contient l'adresse d'un tableau.
    La variable chaine est bien sur la pile mais le tableau "Bonjour\0" ne l'est pas. Il n'est pas non plus sur le tas. Il est dans une autre zone mémoire de données du programme qui n'est pas modifiable que l'on mette const ou pas. Ce qui explique que si tu tentes de modifier cette chaine, il y a plantage. Ceci explique aussi qu'il est bien préférable de la spécifier explicitement const pour éviter de la modifier malencontreusement.

    Par contre, le tableau chaine2 est sur la pile et initialisé par la chaine "Au revoir\0";

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char chaine2[] = "Au revoir\0";
    // est équivalent à :
    char chaine2[] = {'A','u',' ','r','e','v','o','i','r','\0','\0'};
    Alors que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *chaine = "Bonjour\0";
    // n'est pas équivalent à 
    char *chaine = {'B','o','n','j','o','u','r','\0','\0'};
    // ni à 
    char chaine[] = {'B','o','n','j','o','u','r','\0','\0'};

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 121
    Par défaut
    Un grand merci pour cette réponse précise!

    Juste une dernière précision :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Il est dans une autre zone mémoire de données du programme qui n'est pas modifiable
    Comment appeler cet zone mémoire?

  13. #13
    Expert confirmé
    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
    Par défaut
    On peut distinguer 4 zones mémoires :

    1- la pile : allocations automatiques. Variables créées et détruites automatiquement sans intervention explicite du programmeur.

    2- le tas : allocations dynamiques. Variables créées et détruites à la demande explicite du programmeur.

    3- la zone Globales/static : allocations statiques. Utilisée pour les variables globales ou déclarées static. Les variables sont automatiquement créées et initialisées avant le lancement du programme proprement dit et automatiquement détruites en sortie du programme (ce qui a son importance en C++).

    4- la zone de code : contient le code du programme et est en lecture seule.
    Fonctionnellement, les constantes font partie du code (mais pas les variables déclarées const). Pour justifier ce point de vue, remarquons que, parfois, leur valeur peut être même directement inscrite dans le code machine des instructions.

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 121
    Par défaut
    Merci! Merci à tous!
    Ce site est génial.

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

Discussions similaires

  1. Problème de char dans un pointeur de structure
    Par Odawin dans le forum Débuter
    Réponses: 4
    Dernier message: 29/04/2013, 17h02
  2. [C#]Pointeur vers structure
    Par torNAdE dans le forum Windows Forms
    Réponses: 3
    Dernier message: 08/05/2006, 19h43
  3. Réponses: 7
    Dernier message: 08/04/2006, 12h18
  4. Pointeurs et structures...
    Par vinzzzz dans le forum C
    Réponses: 13
    Dernier message: 18/01/2006, 11h37
  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