Quelqu'un peut-il m'expliquer pourquoi mon appel à malloc avec une taille de chaîne de 6 retourne une taille de 4 octets? En fait, tout argument entier que je donne à Malloc, je reçois une taille de 4. Suivant, j'essaie de copier deux chaînes. Pourquoi mon iPut de la chaîne copiée (NULL)? Voici mon code:
int main() { char * str = "string"; char * copy = malloc(sizeof(str) + 1); printf("bytes allocated for copy: %d\n", sizeof(copy)); while(*str != '\0'){ *copy = *str; str++; copy++; } copy = '\0'; printf("%s\n", copy); }
8 Réponses :
Vous obtenez la taille du pointeur STR (4 octets), pas de quoi il pointe? P>
Pourquoi la marque d'interrogation? Vous ne savez pas de votre réponse;) C'est le bon. :)
Pas vraiment. La taille de ce qu'elle pointe (c'est-à-dire
Tailleof (Str) code> renvoie la taille d'un pointeur de type
char * code>. Ce que vous devriez faire, c'est à
MALLOC code> la taille de la chaîne IT SOTE:
while(*copy++ = *str++);
Ils peuvent également être réécrites comme Strcpy (copie, str); code> qui est probablement plus efficace que ce que vous avez.
@Chris oups. J'ai réinventé la roue :)
@Arak: D'accord. Un idiome assez commun en c
@Ed - Je ne dirais pas le commun (pas dans les temps modernes, du moins) mais c'est définitivement largement connu.
Pour l'assurance-santé, il convient de mentionner que cela fonctionne que cela fonctionne parce que les caractères sont un octet, et donc Strlen (Str) donne le Nombre d'octets i> Le texte nécessite (que vous en ajoutez aussi pour que vous puissiez vous adapter à la Terminator NULL). N'oubliez pas que MALLOC (..) prend la taille (en octets) de l'espace alloué en tas dont vous avez besoin comme un argument.
Le code Idiom commun peut également être facile de se tromper. Je remplacerais l'instruction vide ';' code> null avec un
{} code> ou, meilleur encore, un
continuer; code> instruction. Et oui, @lutz,
Strcpy () code> est probablement plus efficace et plus lisible.
Steve McConnell (code complet) a utilisé cet exemple très (Orignally de K & R) en tant que code difficile à lire.
Copy = '\ 0' devrait être * copier = '\ 0'
Comme @paranoidCoder suggère, * copy = '\ 0'; code> est nécessaire pour corriger cette bonne réponse à la autre chose.
alors vous affectez votre pointeur code> copier code> sur un entier qui a la valeur 0 (le caractère Tailleof (str) code> renvoie l'espace nécessaire pour stocker le pointeur sur la chaîne, pas la chaîne elle-même. Vous pouvez voir la taille de la chaîne avec
strallen (str) code> par exemple. P>
'\ 0' code>). C'est la même chose que
copy = null code>, qui est ce que la fonction printf () vous montre. P>
Pour résoudre vos deuxièmes questions, en exécutant la déclaration copie ++ code> Vous avez modifié la valeur de
copier code> (c'est-à-dire l'adresse de la mémoire contenant un
Code> Array) Pour que, au moment où vous l'imprimez, il pointe à la fin de la matrice plutôt que le début (la valeur renvoyée par
malloc () code>). Vous aurez besoin d'une variable supplémentaire pour mettre à jour la chaîne
malloc / taille> code > Problème - Merci CL. P>
char * str = "string";
/* char * copy = malloc(sizeof(str) + 1); Oops */
char * copy = malloc(strlen(str) + 1);
char * original_copy = copy;
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", original_copy);
Il y a toujours un problème avec malloc (taille de (str) + 1) code> -
Tailleof (STR) code> est
Tailleof (Char *) code> est 4 sur la plupart plates-formes, et n'est pas liée à la longueur de la chaîne.
Ah! J'avais oublié que depuis que j'ai incrémenté le pointeur Printf imprimait le caractère null que j'ai ajouté à la fin et non la chaîne entière. Merci beaucoup.
Copy = '\ 0' devrait être * copier = '\ 0'
Tailleforme () renvoie la taille du type réel de la variable. Donc, lorsque vous définissez votre type comme Char *, il renvoie la taille d'un pointeur.
Mais si vous avez modifié votre variable, Tailleof retournerait la taille de la matrice elle-même, ce qui ferait ce que vous voulez faire: p>
Vous devriez inclure Assert (Strlen (PTR) == 10); code> pour la symétrie et l'exhaustivité.
null code>. Li>
- la ligne
copie = '\ 0' code>; Réinitialise le pointeur et le fait null code>. li>
ul>
Le pointeur a été incrémenté à ce moment-là, alors cela ne fait que faire le dernier octet du point de cordon à NULL?
@unknown - non, vous avez laissé l'opérateur de déséroférences. Ce que vous voulez, c'est * copy = '\ 0' code> car
copy = '\ 0' code> définit le pointeur sur
'\ 0' code> (qui est
null code> en tant que type
int code>).
Tout d'abord, vous devriez comprendre que Donc, comme d'autres ont également expliqué que vous devez connaître la longueur de la chaîne que vous souhaitez attribuer, puis ajouter 1 pour stocker le terminal \ 0, C Utilisez implicitement pour mettre à la fin des chaînes. P> mais pour faire ce que vous voulez (copiez une chaîne et allouez l'espace nécessaire), il sera plus simple et plus efficace pour Utilisez Vous ne devez pas non plus oublier d'espace libre Vous vous êtes alloué (utilisant MALLOC, CALOC, STDUP ou toute autre fonction d'allocation). En C, il ne va pas disparaître lorsque la variable allouée est hors de portée. Il restera utilisé jusqu'à la fin du programme. C'est ce que vous appelez une fuite de mémoire. P> un dernier point: j'ai changé de message sur octets au moins alloué em> parce que vous ne connaissez pas vraiment le Taille allouée lorsque vous appelez MALLOC. Il alloue souvent souvent un espace clarquement plus que ce que vous avez demandé. Une des raisons est que, dans de nombreux gestionnaires de mémoire, les blocs libres sont liés ensemble à l'aide de certaines structures de données cachées et tout bloc attribué doit pouvoir contenir au moins une telle structure, une autre est que les blocs alloués sont toujours alignés de manière à être compatible avec n'importe quel type. Alignement. P> J'espère que cela vous aidera à comprendre C un peu mieux. p> p>
Pour ce que ça vaut, STRUP () code> est une fonction non standard, mais il est si trivialement facile de rouler votre propre que ce n'est pas une grosse affaire.
Oui, vous avez raison, il n'est pas standard avec C, même C99, mais très courant (et vous obtenez _strdup, _wcsdup et d'autres autres dans ISO C ++). D'autre part, la mise en œuvre de la bibliothèque est généralement assez optimisée pas si triviale qu'il semble. J'ai vérifié avec GCC sur Linux STDUP si environ 30% plus rapide qu'une boucle de temps et de près de 8% plus rapide que la deuxième meilleure solution que je puisse penser (Malloc puis Strncpy). C'est aussi plus facile à lire. Le grand inconvénient est que MALLOC est caché, d'où les programmeurs oublient souvent libérer les vars STRDUPED. :-(
Vous pouvez utiliser: p>
taille_t malloc_usable_size (vide * PTR); p>
au lieu de: taille de p>
mais il renvoie la taille réelle du bloc de mémoire alloué! Pas la taille que vous avez transmise à malloc! P>
En plus, veuillez arrêter de suggérer des modifications qui défape réponses comme celle-ci: Stackoverflow.com/review/suggested-edits/3830819. Lorsque vous avez la possibilité de commenter, laissez un commentaire si vous êtes en désaccord avec les réponses, mais n'essayez pas de les réécrire vous-même.
Copy = '\ 0' devrait être * copier = '\ 0'