copie d'une chaine de caractères - C - Programmation
Marsh Posté le 24-10-2005 à 14:04:39
Code :
|
Teste ensuite si "p == NULL", des fois que malloc() ait échoué.
Il manque la désallocation qui va avec ton malloc, ajoute un free() quand tu as fini de te servir de p.
Code :
|
Ton pointeur "se déplace". Avant d'incrémenter, il faudrait songer à sauvegarder la position initiale, c'est pourquoi (p-8) fonctionne avec ton printf(), et pas "p" tout court.
Ceci devrait fonctionner :
Code :
|
(sinon tu as strcpy() qui fait ce que tu veux faire )
Marsh Posté le 24-10-2005 à 14:45:29
merci pour la réponse )) mais je comprend pas pourquoi le fait d'utiliser des variables temporaires ca fait que ca marche ? et pourquoi mon pointeur se déplace je suis nul ...
est ce que le while fait :
1 - il incrémente les adresses 1,
2 - assigne la valeur de q à p de la case courante
jusqu'a ce que il tombe sur 0 ..? j'ai bon ? alors pourquoi ca decale tout ..??
Marsh Posté le 24-10-2005 à 14:52:26
ReplyMarsh Posté le 24-10-2005 à 15:13:53
in_your_phion a écrit : merci pour la réponse )) mais je comprend pas pourquoi le fait d'utiliser des variables temporaires ca fait que ca marche ? et pourquoi mon pointeur se déplace je suis nul ... |
Ah flûte, le site d'Emmanuel est down on dirait.
Bon, en gros, un pointeur c'est une variable qui contient une adresse en mémoire. Quand tu l'incrémentes, tu modifies cette variable, et donc tu perds l'information d'origine, à savoir le départ de ton bloc mémoire.
C'est pour ça qu'il faut utiliser d'autres variables et laisser celles d'origine intactes pour conserver l'information.
Marsh Posté le 24-10-2005 à 15:40:26
Elmoricq a écrit : Ah flûte, le site d'Emmanuel est down on dirait. |
ok c'est bon je l'ai fait sur papier j'ai compris merci encore
Marsh Posté le 24-10-2005 à 15:41:36
in_your_phion a écrit : merci pour la réponse )) mais je comprend pas pourquoi le fait d'utiliser des variables temporaires ca fait que ca marche ? et pourquoi mon pointeur se déplace je suis nul ... |
Faut bien que tu comprennes que le C ne connait pas la chaîne de caractères. Il ne connait que l'adresse de début (l'adresse du premier caractère)
Ensuite, si tu veux traiter (afficher) ta chaine, tu utilises une fonction comme "printf" à laquelle tu passes cette adresse. La fonction traite (affiche) le caractère qu'il y a à cette adresse puis passe à l'adresse suivante. Et elle continue d'adresse en adresse jusqu'à trouver une adresse contenant la valeur 0. Là, elle s'arrête de boucler et se finit.
Comme le dit Elmoricq, si tu perds cette adresse de début, ben tu perds ta chaîne...
in_your_phion a écrit : alors que si je fais
|
Tu as perdu ton début de chaine. Mais tu sais le retrouver car tu sais qu'il se trouve 8 positions avant le ptr courant. Tu passes donc à "printf" l'adresse réelle de début de chaine que tu retrouves en calculant "adresse courante - 8"
Ca aurait marché aussi si tu avais écrit
Code :
|
Car, dans un tableau, t[n] <=> *(t + n) et &t[n] <=> t + n
jument a écrit : le pseudo de pholie ! |
Oui, il nous a expliqué que cela n'avait rien à voir à ce à quoi on pense. C'est juste une concaténation de "in your philosophie je sais plus quoi"
Marsh Posté le 24-10-2005 à 16:07:45
Sve@r a écrit : Oui, il nous a expliqué que cela n'avait rien à voir à ce à quoi on pense. C'est juste une concaténation de "in your philosophie je sais plus quoi" |
Marsh Posté le 24-10-2005 à 16:17:11
in_your_phion a écrit : in your philosophy once-over |
heu .. j'ai juste un autre petite question si ca vous dérange pas ..:
quand je fais :
Code :
|
est ce qu'en suite je peux faire
Code :
|
ou faire pointer p sur autre chose ???
et aussi .. quand je fais le test
Code :
|
qu'est ce qui est retourné au while quand la condition n'est plus vérifiée ??? le zéro du fin de la chaine, NULL, ..??
merci encore par avance
Marsh Posté le 24-10-2005 à 19:50:50
ReplyMarsh Posté le 24-10-2005 à 22:22:50
in_your_phion a écrit : heu .. j'ai juste un autre petite question si ca vous dérange pas ..:
|
Q1. Non, tu n'as pas le droit. Sauf si tu veux définitivement perdre l'adresse de la chaîne "Bonjour", qui est statiquement attribuée (à la compilation, enfin plus exactement lors de la mise en mémoire de l'image binaire).
Q2. En fin de chaîne, *q contient 0, donc on obient while(0), donc la boucle s'arrête.
En bref, c'est amusant, mais c'est une ruse de sioux qu'il vaut mieux s'interdire d'utiliser quand on ne s'appelle pas Brian Kernighan, ou Dennis Ritchie ou Ken Thompson.
Par ailleurs, la fonction implémentée de cette manière, à savoir strcpy, a probablement été la source de plus de bugs que toutes les autres fonctions C créées depuis.
Marsh Posté le 26-10-2005 à 17:52:26
el muchacho a écrit : Q1. Non, tu n'as pas le droit. Sauf si tu veux définitivement perdre l'adresse de la chaîne "Bonjour", qui est statiquement attribuée (à la compilation, enfin plus exactement lors de la mise en mémoire de l'image binaire). |
merci .. pour la question 1, est ce que "bonjour" occupe toujours une place mémoire alors ? cette place ne pourra plus etre libérée vu qu'on a perdu l'adresse de départ ?! D'ailleurs je comprend pas pourquoi avec les malloc on se charge de faire un test mémoire et pas pour les tableaux .. les deux occupent pourtant la meme place, alors si ca passe pas avec malloc ca risque pas de passer avec un tableau statique, nan ?
Marsh Posté le 26-10-2005 à 18:59:15
in_your_phion a écrit : D'ailleurs je comprend pas pourquoi avec les malloc on se charge de faire un test mémoire et pas pour les tableaux .. les deux occupent pourtant la meme place, alors si ca passe pas avec malloc ca risque pas de passer avec un tableau statique, nan ? |
Tableaux et malloc() n'adressent pas au même endroit. Si l'allocation d'un tableau échoue, ça plante immédiatement, c'est sans appel.
Tandis que pour malloc(), seul son code retour permet de savoir si l'allocation a échoué ou pas, le programme continue normalement.
Marsh Posté le 26-10-2005 à 19:45:39
Elmoricq a écrit : Tableaux et malloc() n'adressent pas au même endroit. Si l'allocation d'un tableau échoue, ça plante immédiatement, c'est sans appel. |
aaah .. merci pour cette réponse )) donc "bonjour" est toujours sotckée en mémoire et perdue à jamais dans le gosier de la bebete ??? ..mais où donc écrit malloc ? et les tableaux statiques ?? désolé pour toutes ces questions ...
merci encore
Marsh Posté le 26-10-2005 à 20:21:43
Google heap/stack
Marsh Posté le 31-10-2005 à 04:15:49
in_your_phion a écrit :
|
Oui, bien sûr. Un pointeur est une variable. Tu as le droit de le modifier.
Citation : |
Oui, bien sûr. Un pointeur est une variable. Tu as le droit de le modifier.
http://mapage.noos.fr/emdel/notes.htm#pointeurs
Citation :
|
*p (c'est à dire *q). A un certain moment, ça fait 0 et la boucle s'arrête.
Marsh Posté le 31-10-2005 à 04:17:34
el muchacho a écrit : Q1. Non, tu n'as pas le droit. Sauf si tu veux définitivement perdre l'adresse de la chaîne "Bonjour", qui est statiquement attribuée (à la compilation, enfin plus exactement lors de la mise en mémoire de l'image binaire). |
Ben si, c'est permis. Que ce soit utile ou non est une autre histoire, mais ça mord pas.
Marsh Posté le 31-10-2005 à 04:31:04
in_your_phion a écrit : pour la question 1, est ce que "bonjour" occupe toujours une place mémoire alors ? |
Oui. Cet emplacement étant attribué statiquement au démarrage du programme, avant l'appel de main(). il est libéré automatiquement que lorsque le programme se termine. C'est ce qu'on appelle la 'static duration', ou 'durée de vie permanente'.
Citation : cette place ne pourra plus etre libérée vu qu'on a perdu l'adresse de départ ? |
Gni ? Libérée par qui ? Elle n'a pas été allouée par un malloc(). C'est donc pas au programmeur de gérer sa libération. Qu'un pointeur pointe dessus ou non n'influence pas la gestion de la mémoire. De toutes façon, il n'y a roen a gérer si la mémoire est statique. C'est le système qui se débrouille...
char *p = "bonjour"; |
et strictement identique à
char *p; |
Citation : D'ailleurs je comprend pas pourquoi avec les malloc on se charge de faire un test mémoire |
Parce qu'un malloc() peut échouer, et qu'il est effectué pendant l'exécution. Par définition, le chargeur du programme ne peut pas prévoir quelle mémoire dynamique va être utilisée. Il ne peut donc pas réserver quoique ce soit.
Citation : et pas pour les tableaux .. les deux occupent pourtant la meme place, alors si ca passe pas avec malloc ca risque pas de passer avec un tableau statique, nan ? |
Un tableau statique a une taille connue à la compilation. Le loader peut donc savoir qu'il lui faudra tant de kbytes pour pouvoir charger le programme. Ensuite, il paut ou non. Il y a des programmes qui commencent par un 'out of memeory", parce qu'il n'y a pas assez de place libre pour le chargement.
Ce qui peut aussi arriver c'est que la somme des variables statiques dépasse la taille possible pour un segment de donnée. Dans ce cas, c'est le linker qui rale (très courant en 16-bit avec les pages de 64k).
Enfin, un tableau défini en mémoire automatique (pile en général) peut être trop grand pour celle-ci. Le comportement est alors indéfini, et tout peut arriver, y compris un semblant de fonctionnement correct... A éviter absolument.
Le plus sûr, c'est de tendre vers le 100% dynamique. Tous les programmes sérieux fonctionnent comme ça...
Marsh Posté le 31-10-2005 à 04:39:08
in_your_phion a écrit : aaah .. merci pour cette réponse )) donc "bonjour" est toujours sotckée en mémoire et perdue à jamais dans le gosier de la bebete ??? ..mais où donc écrit malloc ? et les tableaux statiques ?? désolé pour toutes ces questions ... |
Bases du C : Un processus utilise de la mémoire pour ses données :
Celle-ci se divise en 3 zones :
- Mémoire statique
- Mémoire automatique
- Mémoire dynamique
La zone statique comprend les chaines, les variable éfinies hors bloc, ou en block avec le mot clé 'static'. La taille est connue au chargement. L'initialisation est faite avant le main().
La zone automatique (souvent implémentée par une pile d'une taille relativement faible) permet de créer des variables dont la durée de vie est limitée à un bloc. L'allocation et la libérartion, sont, comme sont nom l'indique, automatiques. On l'utilise pour les variables locales ('jetables').
La zone dynamique utilise toute la mémoire libre du processus. Elle est réservée par malloc() et rendue par free().
Les détails (segments etc.) appartiennent aux implémentations.
Marsh Posté le 07-11-2005 à 15:06:07
Emmanuel Delahaye a écrit :
|
AAaaAaaaAaAaAhhHHhhh.... je me meurs . Je ne comprend pas .. ca veut dire que "p" qui est une case qui normalement contient un chiffre qui correspond à une adresse peut aussi contenir une chaine de caractères ?! .. ..pourquoi ? je croyais que les pointeurs devaient seulement contenir des adresses mémoires? on peut mettre d'autres trucs dedans alors ? comme des double, int, char ..etc ?
merci par avance pour vos explications mirifiques
Marsh Posté le 07-11-2005 à 15:17:24
p contient l'adresse vers un bloc mémoire qui contient plusieurs char.
"bonjour" est une suite de char terminés par le caractère '\0'.
Quand tu écris :
char *p = "bonjour"; |
Tu dis, en clair : p reçoit l'adresse à laquelle se trouve la chaîne "bonjour".
Marsh Posté le 07-11-2005 à 15:42:09
Elmoricq a écrit : p contient l'adresse vers un bloc mémoire qui contient plusieurs char.
|
ah ok merci ! pfiou .. j'ai failli faire un arrêt cardiaque faut que je me calme là ...
mais alors, pourquoi on peut pas faire int *p = 10; .. ca pourrait tout simplement vouloir dire que p contient l'adresse du nombre 10..gah.
Marsh Posté le 07-11-2005 à 15:46:50
in_your_phion a écrit : mais alors, pourquoi on peut pas faire int *p = 10; .. ca pourrait tout simplement vouloir dire que p contient l'adresse du nombre 10 |
Et c'est quoi l'adresse d'une constante ?
Marsh Posté le 07-11-2005 à 15:52:41
Emmanuel Delahaye a écrit : Et c'est quoi l'adresse d'une constante ? |
heu .. ben c'est &constante ? ...ce que je comprend pas c'est que quand on dit
Code :
|
bah c'est bien une chaine constante la, non ? alors pourquoi ca marche pour les char et pas pour les chaines d'entiers ?
Marsh Posté le 07-11-2005 à 16:02:40
in_your_phion a écrit : heu .. ben c'est &constante ? ... |
Non. Par définition, une constante n'a pas d'adresse.
Citation :
|
Non. C'est une chaine littérale. C'est en fait un tableau de char initilisé non modifiable, et elle a une adresse de type char* qui est celle de son premier caractère. Ce n'est pas une expression constante. Il est d'ailleurs recommandé d'écrire
char const *p = "bonjour"; |
10 n'est pas une 'chaine d'entier'. C'est une valeur constante. (En assembleur, on dit 'valeur immédiate')
Marsh Posté le 07-11-2005 à 16:12:58
Tiens d'ailleurs, question stupide : pourquoi {int 1, int 2, ..., int n} n'est pas compatible avec int* ?
Marsh Posté le 07-11-2005 à 16:13:23
Emmanuel Delahaye a écrit : Non. Par définition, une constante n'a pas d'adresse.
Non. C'est une chaine littérale. C'est en fait un tableau de char initilisé non modifiable, et elle a une adresse de type char* qui est celle de son premier caractère. Ce n'est pas une expression constante. Il est d'ailleurs recommandé d'écrire
|
d'accord, merci beaucoup pour cette explication. Donc est ce qu'on peut dire que
Code :
|
est un abu de langage ? puisque c'est en fait char p[6] = "bonjour"; ??
heu ...et quand on dit
Code :
|
est-ce pareil que
Code :
|
Merci encore
Marsh Posté le 07-11-2005 à 16:17:28
in_your_phion a écrit : Donc est ce qu'on peut dire que
|
Pourquoi 6 ?!
"char p[6]" définit une variable p de type "tableau de 6 caractères" (d'ailleurs il t'en faut 8 pour stocker "bonjour" : 7 pour les lettres, et 1 caractère de fin de chaîne qui est implicitement ajouté).
"char *p" définit une variable de type "adresse vers n char"
Donc :
const char *p = "bonjour";
n'est pas un abus de langage.
Marsh Posté le 07-11-2005 à 16:29:10
Elmoricq a écrit : Pourquoi 6 ?! |
d'oh. En effet je me suis trompé, c'est 8 , enfin 7 ? char p[7]
haa .. alors je crois que je commence vaguement a comprendre. Mais alors du coup, pourquoi une constante n'a pas d'adresse ? ca veut dire que char p[6] n'a pas d'adresse ???? et le symbole "&" ca sert quand meme pour les constantes, non ?
Marsh Posté le 07-11-2005 à 16:31:40
in_your_phion a écrit : d'accord, merci beaucoup pour cette explication. Donc est ce qu'on peut dire que
|
Non, c'est autre chose. Tu confonds pointeur et tableau.
On peut faire ça :
/* tableau de char initialise */
char s[] = "bonjour";
/* pointeur sur char initialise avec l'adresse du premier element d'un tableau de char */
char *p = s;
Citation :
|
Oui.
Marsh Posté le 07-11-2005 à 16:37:09
in_your_phion a écrit : haa .. alors je crois que je commence vaguement a comprendre. Mais alors du coup, pourquoi une constante n'a pas d'adresse ? |
Je me tue à te dire que par définition, une constante n'a pas d'adresse.. C'est un axiome, une affirmation, ça ne ce démontre pas. C'est comme ça, c'est tout. Si ça a une adresse, c'est un objet.
Citation : |
Gné ? Tu trouves que char p[6], ça a une tronche de constante ? C'est un tableau de char, et il a une adresse. (je te fais grâce de son type, qui n'est pas char*)
Citation : et le symbole "&" ca sert quand meme pour les constantes, non ? |
Ben non. Essaye, tu te prends une erreur de syntaxe.
|
|
Marsh Posté le 07-11-2005 à 16:37:43
Emmanuel Delahaye a écrit : Non, c'est autre chose. Tu confonds pointeur et tableau. |
bah ...ça je comprend. Ce que je comprend moins c'est de dire
Code :
|
vu que on est censé donner une adresse, comme dans ton exemple quand on fait
Code :
|
...
Citation :
|
ok merci
Marsh Posté le 07-11-2005 à 16:43:46
Emmanuel Delahaye a écrit : Je me tue à te dire que par définition, une constante n'a pas d'adresse.. C'est un axiome, une affirmation, ça ne ce démontre pas. C'est comme ça, c'est tout. Si ça a une adresse, c'est un objet.
|
ok, mais quand je fais :
Code :
|
j'ai pas d'erreur, et pourtant a est une constante, nan
Marsh Posté le 07-11-2005 à 16:46:11
ReplyMarsh Posté le 07-11-2005 à 16:50:57
ReplyMarsh Posté le 07-11-2005 à 16:53:37
quand tu ecris char *p = "bonjour"; ce n'est pas p qui est constant, c'est la chaine pointée qui l'est.
edit : ou tout du moins qui devrait l'etre.
Marsh Posté le 07-11-2005 à 18:58:54
blackgoddess a écrit : quand tu ecris char *p = "bonjour"; ce n'est pas p qui est constant, c'est la chaine pointée qui l'est. |
Non, elle n'est pas constante. Elle est non modifiable. Merci de ne pas confondre 'expression constante' et 'objet non modifiable'. C'est ce que je me tue à essayer d'expliquer au P.O...
Marsh Posté le 07-11-2005 à 19:06:12
in_your_phion a écrit :
|
Non (manque un void*). a n'est certainement pas une constante, la preuve, c'est que tu a résussi à prendre son adresse, preuve que c'est une objet.
Ce code fonctionne aussi :
|
C'est un objet de type int initialisé avec une valeur. C'est la valeur en elle même qui est une constante. Mais une fois qu'elle a été copiée dans la variable, celle-ci (la variable) ne devient pas magiquement une constante, même si on ajoute le mot clé 'const', qui, rappelons-le une ènième fois, transforme un objet modifiable en un objet non modifiable.
Mais ça reste un objet. Certainement pas une constante. Je rappelle qu'une constante n'a pas d'adresse et n'est donc pas un objet.
Marsh Posté le 24-10-2005 à 13:56:30
bonjour,
je voudrai copier une chaine de caractères dans une autre avec while (*p++ = *q++); (et pas d'une autre manière, je sais qu'y fo pas faire comme ca ..)
j'ai ecrit le programme et ça marche pas dans l'affichage a la fin, je comprend pas
alors que si je fais
ca marche. Kesako ?
merci par avance
Message édité par in_your_phion le 24-10-2005 à 13:56:57