#1 Le 29/08/2013, à 19:15
- neokal
[RESOLU] Question générale de débutant sur les chaines en language C
Bonsoir à tous,
Je débute en C et j'aurais besoin d'un peu d'éclaircissement, en effet j'ai du mal a trouver mes réponses dans les différents tuto.
Je déclare certaine variable de cette façon
char * machaine1;
et
char machaine2[255];
j'ai du mal à comprendre l'intérét de la seconde ci ce n'est par exemple que la fonction strcat accépte uniquement les chaines déclarées de la seconde maniére.
Pourquoi? je n'en sais rien, ça à l'air de marcher selon les fonctions, au petit bonheur :-)
Maintenant j'ai une chaine (une commande mysql bricoler a l'aide de strcat et qui se termine par \0 je précise) déclarer de la 2eme facon que je copie vers celle déclarer de la 1er maniére , quand je l'affiche seul aucun probléme
printf("%s\n",commandemysql);
renvoi
INSERT INTO clients (id,prenom,nom,ville) VALUES('5','Pierre','Martin','Bordeaux')
mais
printf("%s\nICI une suite normal",commandemysql);
renvoi
INSERT IH (genre de point d'interrogation??)
ICI une suite normal
J'avais lu quelque part que si elle était mal déclaré elle avait un fonctionnement imprévisible, bref je me doute que ma solution consiste a copié X éléments de la chaines (jusqu'a \0) dans ma chaine char * machaine1 ou alors de déclarer char machaine2[255] aussi pour que ma commande devienne enfin valide mais ce que j'aimerais c'est surtout comprendre POURQUOI ce fonctionnement a deux vitesses, quels sont les différents cas de figure enfin bref si un prof veux bien m'expliquer le cour :-)
Merci
Dernière modification par neokal (Le 05/10/2013, à 18:33)
Celui qui se transforme en bête se délivre de la douleur d'être un homme...
Hors ligne
#2 Le 29/08/2013, à 19:37
- pingouinux
Re : [RESOLU] Question générale de débutant sur les chaines en language C
Bonsoir,
Dans ton exemple ci-dessus :
machaine1 est un pointeur de caractères, qui pointe sur n'importe quoi car il n'est pas initialisé. Il faudrait l'initialiser en le faisant pointer sur une zone de mémoire, comme ceci par exemple :
machaine1=(char*)malloc(255);
machaine2 est un tableau de 255 caractères, prêt à être utilisé
Remarque : N'oublie pas les ";" à la fin des commandes.
Dernière modification par pingouinux (Le 29/08/2013, à 19:57)
Hors ligne
#3 Le 29/08/2013, à 20:33
- neokal
Re : [RESOLU] Question générale de débutant sur les chaines en language C
en gros
char * machaine1;
machaine1=(char*)malloc(255);
equivaut à
char machaine2[255];
en clair * défini juste une variable et j'initialise le nombre d'éléments au moment ou je l'utilise?
petite question? -> puis je modifier le nombre d'éléments du tableau une seconde fois aprés avoir initialiser (suivant une méthode ou l'autre)
Et d'ou vienne mes caractéres étranges?
Dernière modification par neokal (Le 29/08/2013, à 20:34)
Celui qui se transforme en bête se délivre de la douleur d'être un homme...
Hors ligne
#4 Le 29/08/2013, à 22:23
- pingouinux
Re : [RESOLU] Question générale de débutant sur les chaines en language C
On peut modifier la taille de la zone de mémoire pointée par machaine1, mais pas par machaine2. Voici une méthode :
machaine1=(char*)realloc(machaine1,nouvelle_taille);
Dès l'instant où on utilise une zone de mémoire non allouée et qui peut contenir n'importe quoi, on obtient n'importe quoi.
Hors ligne
#5 Le 30/08/2013, à 07:45
- tiramiseb
Re : [RESOLU] Question générale de débutant sur les chaines en language C
en clair * défini juste une variable
Non, ça définit un pointeur.
C'est très important de comprendre ce que sont les pointeurs en C...
Sébastien Maccagnoni - https://www.maccagnoni.eu - https://www.domotego.com
Hors ligne
#6 Le 30/08/2013, à 20:40
- neokal
Re : [RESOLU] Question générale de débutant sur les chaines en language C
oui j'ai lu une page bien expliquer tout à l'heure sur ce que sont les pointeurs, je commence a comprendre l'importance d'absolument faire la différence :-)
merci pingouinux pour la méthode de realloc, ça pourra m'aider dans l'avenir.
j'ai un petit soucis qui vaut probablement pas la peine de réouvrir un topic
j'utilise une fonction qui retourne l'adresse d'une chaine, pas de probléme vu que je récupére dans le 'main' par une autre adresse de chaine, tout marche bien mais quand je compile j'ai un message du genre
attention : cette fonction retourne l'adresse d'une variable locale [enabled by default]
Est ce grave? Peut etre que la il y a un probléme dans ma méthode? Je me dit que si gcc prend la peine de me le dire c'est qu'il peu y avoir des problémes avenir,
En gros simple avertissement ou quelque chose de plus grave?
Merci pour votre aide en tous les cas
Celui qui se transforme en bête se délivre de la douleur d'être un homme...
Hors ligne
#7 Le 31/08/2013, à 02:40
- Melrock
Re : [RESOLU] Question générale de débutant sur les chaines en language C
attention : cette fonction retourne l'adresse d'une variable locale [enabled by default]
Est ce grave? Peut etre que la il y a un probléme dans ma méthode? Je me dit que si gcc prend la peine de me le dire c'est qu'il peu y avoir des problémes avenir,
En gros simple avertissement ou quelque chose de plus grave?
Quelque chose de plus grave !
Quand on lance une fonction, on alloue automatiquement les variables locales de cette fonction/
Quand la fonction se termine (avec return, ou en arrivant à la fin) les variables locales sont désallouées.
Si une fonction retourne l'adresse d'une variable locale, cette adresse pointe donc vers une zone mémoire qui n'est plus allouée (puisqu'on est sorti de la fonction), donc disponible pour toute fonction qui en aurait besoin.
Dès que tu appelle une fonction, tu risques donc de modifier "aléatoirement" la valeur de ta variable.
Par exemple en ajoutant un printf() entre l'appel de ta fonction et l'utilisation de l'adresse retournée, tu risques un comportement aberrant.
Il y a différentes solutions :
- déclarer "static" la variable dont tu retournes l'adresse. Ainsi elle a une adresse fixe, la même à chaque appel de la fonction, qu'on peut utiliser en dehors de la fonction. L'inconvénient est justement que c'est toujours la même variable : chaque appel à la fonction retournera la même adresse et modifiera le résultat précédent.
- allouer dynamiquement la variable (par exemple avec malloc()). L'inconvénient est qu'il faudra prévoir de libérer la mémoire : chaque appel de la fonction consomme de la mémoire.
- passer en paramètre à ta fonction l'adresse de la variable dans la quelle elle doit donner son résultat (comme on le fait, par exemple avec strcat())
- utiliser une variable globale (inutile, dans ce cas de retourner sa valeur puisqu'elle est accessible partout). A consommer avec modération ! On peut tout faire avec des variables globales, mais c'est difficile de faire quelque chose de clair et bien structuré.
- travailler en programmation objet (C++), la variable en question étant un attribut d'une classe dont une méthode fixe la valeur (de la variable) et une autre l'utilise. Ça demande une réflexion fouillée pour définir clairement les classes de ton projet.
- et j'en oublie sûrement !
J'ajoute que tu te poses (à mon avis) les bonnes questions. continue !
Tout problème a sa solution, donc s'il n'y a pas de solution, c'est qu'il n'y a pas de problème.
Hors ligne
#8 Le 31/08/2013, à 10:02
- telliam
Re : [RESOLU] Question générale de débutant sur les chaines en language C
Si une fonction retourne l'adresse d'une variable locale, cette adresse pointe donc vers une zone mémoire qui n'est plus allouée (puisqu'on est sorti de la fonction), donc disponible pour toute fonction qui en aurait besoin.
Non c'est incorrect, une variable locale est une variable de la pile, elle est donc toujours "allouée" (bien que le terme n'est pas tres juste dans ce cas la), tu vas donc pointer sur une adresse dont le contenu ne peux plus etre 'garanti', si tu y accèdes en lecture tu risques de trouver des données incohérentes ( le cas le pire dans le cas de manipulation de chaines de characteres est la perte du /0 terminal), si tu y accèdes en écriture, tu risques d'écraser ta pile et donc les contextes d'appel et donc de planter ton programme.
"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard
Hors ligne
#9 Le 01/09/2013, à 04:53
- Melrock
Re : [RESOLU] Question générale de débutant sur les chaines en language C
Melrock a écrit :Si une fonction retourne l'adresse d'une variable locale, cette adresse pointe donc vers une zone mémoire qui n'est plus allouée (puisqu'on est sorti de la fonction), donc disponible pour toute fonction qui en aurait besoin.
Non c'est incorrect, une variable locale est une variable de la pile, elle est donc toujours "allouée" (bien que le terme n'est pas tres juste dans ce cas la), tu vas donc pointer sur une adresse dont le contenu ne peux plus etre 'garanti', si tu y accèdes en lecture tu risques de trouver des données incohérentes ( le cas le pire dans le cas de manipulation de chaines de characteres est la perte du /0 terminal), si tu y accèdes en écriture, tu risques d'écraser ta pile et donc les contextes d'appel et donc de planter ton programme.
Là tu mélanges joyeusement définition du langage et implémentation. La norme C99 parle juste d' "automatic storage duration" (durée de stockage automatique) en disant qu'elle commence quand on entre dans le bloc où est définie une variable automatique et se termine quand on en sort.
Mais bien sûr, les choses se passent comme tu le décris (Sauf que pour moi le cas le pire c'est pas quand le programme plante, c'est quand une variable prend une valeur fausse mais vraisemblable. Parce que pour debugger ...
)
Tout problème a sa solution, donc s'il n'y a pas de solution, c'est qu'il n'y a pas de problème.
Hors ligne
#10 Le 01/09/2013, à 09:09
- telliam
Re : [RESOLU] Question générale de débutant sur les chaines en language C
C'est possible, je connais plus l'implémentation de gcc que la norme offcielle
effectivement débugger un programme qui prend une valeur fausse, ça peut etre assez joyeux à faire
Quoique un écrasement de pile, ça peut etre velu dans certains cas:)
"- Un intellectuel assis va moins loin qu'un con qui marche."
Maurice Biraud - Un Taxi pour Tobrouk
Michel Audiard
Hors ligne
#11 Le 05/10/2013, à 18:33
- neokal
Re : [RESOLU] Question générale de débutant sur les chaines en language C
Bonjour,
Désolé de répondre aussi tard que maintenant mais mieux vaut tard que jamais,
Un grand merci pour vos réponses (surtout Melrock, merci pour les solutions 'static' ou 'global') vous m'avez beaucoup aidé dans mon probléme.
Merci à tous )
Celui qui se transforme en bête se délivre de la douleur d'être un homme...
Hors ligne