Le tableau animals
est un tableau de pointeurs. Ce n'est pas un tableau de tampons de quelque taille. Par conséquent, si vous le faites
sizeof(*animals)
Vous obtiendrez le sizeof du premier élément de ce tableau. Équivalent à
sizeof(char*)
Parce que votre tableau stocke des pointeurs. Ainsi, dans la ligne qui lit
char *output[sizeof(*animals)];
vous allouez 4 ou 8 pointeurs dans un tableau (dépend de la largeur d'un pointeur sur votre plate-forme est. Habituellement, il est 4 ou 8). Mais ce n'est bien sûr pas sensé! Ce que vous vouliez faire est de créer un tableau de pointeurs de la même taille que animals
. Vous devrez d'abord obtenir la taille totale du tableau des animaux, puis diviser par la taille d'un élément
char *output[sizeof(animals)/sizeof(*animals)];
Maintenant, c'est-ce que vous voulez. Mais les pointeurs auront encore des valeurs indéterminées ... Ensuite, vous passez le tableau en utilisant *&animals
(même chose pour l'autre). Pourquoi ça? Vous pouvez passer directement au animals
. Prendre son adresse, puis déréférencer est la même chose que de ne rien faire en premier lieu.
Puis dans la fonction que vous appelez, vous copiez les chaînes pointées par des éléments en animal
vers une destination indéterminée (rappelez-vous les éléments du tableau output
- les pointeurs -.! Ont des valeurs encore indéterminées Nous ne les ont pas encore assignés) . Vous devez d'abord allouer la bonne quantité de mémoire et faire pointer les éléments vers cela.
while(*animals) {
// now after this line, the pointer points to something sensible
*output = malloc(sizeof("new animal ") + strlen(*animals));
sprintf(*output, "new animal %s", *animals);
output++; // no need to dereference the result
animals++; // don't forget to increment animals too!
}
addition, sur le sizeof ci-dessus
Il y a une chose importante que vous devez être sûr. C'est la façon dont nous calculons la taille. Quoi que vous fassiez, assurez-vous de toujours avoir assez de place pour votre chaîne! Une chaîne C se compose de caractères et d'un caractère nul final, qui marque la fin de la chaîne. Donc, *output
doit pointer vers un tampon qui est au moins aussi grand afin qu'il contienne de l'espace pour "new animal "
et *animals
. Le premier contient 11 caractères. La seconde dépend de ce que nous copions réellement - sa longueur est ce que strlen
renvoie. Donc, au total, nous avons besoin
12 + strlen(*animals)
espace pour tous les caractères, y compris la valeur nulle. Maintenant, ce n'est pas un bon style de coder en dur ce numéro dans votre code.Le préfixe pourrait changer et vous pourriez oublier de mettre à jour le nombre ou un compte approximatif d'un ou deux caractères. C'est pourquoi nous utilisons sizeof
, que nous fournissons avec le littéral de chaîne que nous voulons avoir pré-ajouté. Rappelons qu'une expression sizeof
évalue à la taille de son opérande. Vous l'utilisez dans main
pour obtenir la taille totale de votre tableau avant. Maintenant vous l'utilisez pour le littéral de chaîne. Tous les littéraux de chaîne sont des tableaux de caractères. Les littéraux de chaîne se composent des caractères que vous tapez en plus au caractère nul. Ainsi, la condition suivante est, parce que strlen
compte de la longueur d'une chaîne de C, et ne comprend pas le caractère nul final à sa longueur
// "abc" would have the type char[4] (array of 4 characters)
sizeof "..." == strlen("...") + 1
Nous ne devons pas diviser par la taille d'un élément, parce que le sizeof char n'en est pas moins un, donc ça ne fera pas de différence. Pourquoi utilisons-nous sizeof
au lieu de strlen? Parce qu'il prend déjà en compte le caractère nul final et qu'il évalue au moment de la compilation. Le compilateur peut littéralement substituer la taille renvoyée par l'expression sizeof.
Vous avez besoin de +1 pour la longueur du terminateur null. – dirkgently
le sizeof d'un littéral de chaîne inclut déjà le terminateur null :) so sizeof "" == 1 –