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 :

string dans un struc : allocation de mémoire ?


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut string dans un struc : allocation de mémoire ?
    Bonjour,

    je sature apres avoir trouvé un formidable bug.

    J'ai un struct, disons :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct {
    char string1[3];
    char string2[3];
    } enzyme;
    Plus loins mon code je crée un tableau d'enzymes (avec malloc). Disons enzymes.
    Plus loins dans mon code, j'affecte des caractères à chacuns de mes strings (un par un) de chacuns des éléments enzyme de mon tableau enzymes.
    Je termine par un '\0' à la 3ème position. Normal.
    Ce qui est moin normal c'est que mes string1 commencent sytématiquement par un \0.
    En cherchant j'ai découvert que les 2 strings étaient contigues en mémoire !!! (normal me dira un habitué...). Du coup le '\0' de string2 correspond à l'index 0 de string1.

    J'en conclu ma bêtise et qu'il faut donc que je fasse un malloc (voire calloc) à la création de mes struct mais je vois pas comment faire dans cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    enzymes = (enzyme*) malloc (enzyme_numb*sizeof(enzyme));
    J'ai une limitation de mon cerveau.
    J'aurais voulu faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    typedef struct {
    char* string1 = calloc(3*sizeof(char);
    char* string2 = calloc(3*sizeof(char);
    } enzyme;
    Pouvez-vous m'éclairer!!

    Merci d'avance, yann

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Ben non, pas d'allocation dynamique supplémentaire nécessaire, c'est normal que tes strings soient contigües.

    Par contre, qu'appelles-tu exactement "à la 3ème position" ? (montre le code)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Salut,

    Je pense pas que ce soit une obligation du compilateur de rendre les 2 chaines contigues en mémoire. Je pense que dans une logique portable, on ne devrait pas se baser dessus.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    Trop dure vraiment de montrer le code, j'ai vraiment essayé de simplifier au max.

    Disons que string2[3] est au même endroit de la mémoire que string1[0].
    Du coup string2[4] == string1[1] !!
    Ce pour chaque enzymes[i] ( par exemple enzymes[2].string2[4] == enzymes[2].string1[1] )

    Je dois partir manger je reprend dans 45 minutes.

    Merci Médinoc !

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Gruik: Mais là, wonderyan n'utilise pas le fait que les chaînes soit contigües, il en souffre.
    Probablement parce qu'il déborde de string2 en écrivant son \0 à la 4e place au lieu de la 3e...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    (post croisé)
    Bingo!
    string2[3] ne correspond pas au 3e caractère, mais au 4e.
    En C, les tableaux commencent à zéro, pas à 1...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Oki, bein, il faut que tu te premunisse des depassements de tableau.. avec strncpy par exemple (sans oublier de rajouter le \0), ou avec snprintf(C99).
    Utiliser des constantes symboliques indiquant la longueur max des chaines qu'on peut mettre dans ces tableaux peut être une bonne idée

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    EDIT : j'avais pas vu vos nouveaux messages du coup je refait ce message.

    Je souffre effectivment de cette contiguité !!
    Mais Médinoc je ne comprend pas pourquoi tu me dits que ça commence à 0. Je le sais.
    Et comme je veux que ma chaine se termine au 4eme index, je met mon '\0' là ???

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    trinucl_sens[3]='\0';
    trinucl_anti[3]='\0';
    j'ai déjà répondu...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    Ca se passe dans cette fonction
    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
     
    int get_trinucls(char* sequence, int position_start, int position_end, char* trinucl_sens, char* trinucl_anti, int cut_rank) {
    	int j;
    	char base_anti, base_sens;
    	for (j=0; j<3; j++) {
    		base_anti = sequence[position_end-cut_rank-j-1];
    		base_sens = sequence[position_start+j+(ENZYME_LEN-cut_rank)-1];
    		if( (base_anti == 'a' || base_anti == 'c' || base_anti == 'g' || base_anti == 't') && (base_sens == 'a' || base_sens == 'c' || base_sens == 'g' || base_sens == 't') ) {
    			trinucl_sens[j] = base_sens;
    // 			if (j == 0) printf("%c", trinucl_sens[j]);
    			switch (base_anti) {
    				case 'a' : base_anti = 't'; break;
    				case 'c' : base_anti = 'g'; break;
    				case 'g' : base_anti = 'c'; break;
    				case 't' : base_anti = 'a'; break;
    			}
    			trinucl_anti[j] = base_anti;
    		}
    		else {
    			return 0;
    		}
    	}
    	trinucl_sens[3]='\0';
    	trinucl_anti[3]='\0';
    // 	printf("\n");
    //      et là j'ai exactement les memes caractères !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    	printf("%c\t%c\n", trinucl_anti[4], trinucl_sens[1]);
    // 	printf("%s\t%u\t%s\t%u\t%s\n", psub->name, position_start, trinucl_sens, position_end, trinucl_anti);
    	return 1;
    }

  11. #11
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Lis-tu mes posts ??
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    oui oui je les lis mais je ne comprends pas!!

    Un exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    string1[0] = 'y';
    string1[1] = 'a';
    string1[2] = 'n';
    string1[3] = '\0';
    printf("%s", string1);
     
    ==>> retourne : "yan" ????
    On est d'accord ??

  13. #13
    Membre chevronné Avatar de dapounet
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2007
    Messages
    469
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2007
    Messages : 469
    Par défaut
    Si tu veux utiliser quatre caractères pour chaque chaîne tu déclares

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    typedef struct
    {
       char string1[4];
       char string2[4];
    } enzyme;
    Et c'est bon.

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    Hum sinon je vais tester d'appeller des string dans ma struct non pas de 3 mais 4 charactères

    Soit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    typedef struct {
    char string1[4];
    char string2[4];
    } enzyme;
    et controler moi meme leur tailel grace au '\0' ???

    J teste et vous dit mais j'imagine qu'il y a plus propre. Et puis ça serait cool de capter ce qui se passe.

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    Whoua j suis désolé c'est qui je coupais la parole à tout le monde .

    En fait je crois qu'il faut que l'on me précise un fondamental à côté duquel je suis passé;

    J'appel une chaine comme ça : char string[3]
    -> ça me réserve 4 "cases" dans la mémoire vive ???
    Et la 4ème on s'en sert pour mettre le caractère null qui termine une chaine c'est ça??

    Donc si je créé une chaine string[4] je vais avoir 5 cases dont une pour terminer?
    C'est bisare il ne m'en faut que 3 (donc de l'index 0 à 2) mais avec 4 j'aurais pas ce bug......

    Qu'est ce que c'est chaud le C quand meme... on remet tout en question .....

  16. #16
    Membre expérimenté
    Inscrit en
    Mai 2007
    Messages
    335
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 335
    Par défaut
    C'est difficile les débuts oui
    effectivement, il faut bien relire les posts de Médinoc qui donne la solution: en faisant simple:

    char string1[4];// réserve 4 caractères. (et pas 5 ni 3)
    \0 prend un caractère.
    tu as le droit d'écrire
    string1[0]='a';
    string1[1]='a';
    string1[2]='a';
    string1[3]='\0';

    tu ne doit pas affecter de valeur à string1[4]: sinon c'est un dépassement mémoire.

    La fonction strcpy citée plus haut permet déjà de s'arrêter automatiquement au \0.

    edit et corrections: je voulais parler de Médinoc, je m'ai gourré.

  17. #17
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    Oui ca marche mais ca m'embrouille aussi.
    Bon bah si quequ'un un jour à la meme galère si ça pourra lui servire.

    Dans 15 minutes je tag ce post comme résolut mais pas tout à fait à mon gout.

    Je vous remercie tous très fort pour votre dévouement.
    Bonne journée,

    yan

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    Ok bah c'est bon c'est ultra résolut.

    Je suis réellement passé à coté d'un fondamental!...

    Merci les gars

  19. #19
    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 : 48
    Localisation : Suisse

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par wonderyan Voir le message
    Whoua j suis désolé c'est qui je coupais la parole à tout le monde .

    En fait je crois qu'il faut que l'on me précise un fondamental à côté duquel je suis passé;

    J'appel une chaine comme ça : char string[3]
    -> ça me réserve 4 "cases" dans la mémoire vive ???
    Et la 4ème on s'en sert pour mettre le caractère null qui termine une chaine c'est ça??

    Donc si je créé une chaine string[4] je vais avoir 5 cases dont une pour terminer?
    C'est bisare il ne m'en faut que 3 (donc de l'index 0 à 2) mais avec 4 j'aurais pas ce bug......

    Qu'est ce que c'est chaud le C quand meme... on remet tout en question .....
    Non, la définition suivante:
    ;
    reserve l'espace pour 6 caractères sur la pile. On peut initialiser un tel tableau de caractères lors de la définition de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char message[6] = "Salut";
    qui est strictement équivalent à:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char message[6] = {'S', 'a', 'l', 'u', 't', '\0'};
    C'est au programmeur de prévoir l'espace nécessaire pour le caractère nul de terminaison de chaines. Mais ça, si tu avais lu les posts de Médinoc...

    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++

    +

  20. #20
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    82
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 82
    Par défaut
    Mais oui je suis désolé Médinoc je ne pouvais pas comprendre parceque ton exemple je le comprennais comme j'ai toujour cru comprendre.
    Désolé

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

Discussions similaires

  1. Problème d'allocation de mémoire dans la pile
    Par prophet666 dans le forum x86 32-bits / 64-bits
    Réponses: 6
    Dernier message: 19/01/2006, 02h22
  2. Integer ou string dans une DBGRID
    Par Yepazix dans le forum Bases de données
    Réponses: 4
    Dernier message: 02/08/2004, 13h42
  3. problème our passer des string dans tableau d'int
    Par Battosaiii dans le forum C++
    Réponses: 9
    Dernier message: 15/07/2004, 17h42
  4. Réponses: 6
    Dernier message: 24/07/2003, 12h39
  5. Recherche d'un String dans un String ?
    Par apen2k2 dans le forum Langage
    Réponses: 9
    Dernier message: 14/04/2003, 11h08

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