Je suis venu vous déranger tout avec une autre question probablement vraiment simple c.
Utilisation du code suivant: p>
int get_len(char *string){ printf("len: %lu\n", strlen(string)); return 0; } int main(){ char *x = "test"; char y[4] = {'t','e','s','t'}; get_len(x); // len: 4 get_len(y); // len: 6 return 0; }
9 Réponses :
Vous avez besoin de null-terminer Y.
int get_len(char *string){ printf("len: %lu\n", strlen(string)); return 0; } int main(){ char *x = "test"; char y[5] = {'t','e','s','t','\0'}; get_len(x); // len: 4 get_len(y); // len: 4 return 0; }
Alors, Strlen vient de renvoyer le pointeur jusqu'à ce qu'il trouve une autre \ 0 partout où elle peut?
Deux problèmes avec cela. Premièrement, NULL est conçu comme un pointeur NULL, pas un caractère nul. Deuxièmement, vous avez toujours CHAR Y [4] CODE>, vous avez donc un initialiseur supplémentaire. Vous avez besoin de cinq positions pour avoir une chaîne de "test".
Désolé, j'ai oublié d'incrémenter l'index, mais je ne savais pas la chose nulle. Apprenez quelque chose de nouveau tous les jours.
Voici quoi Une implémentation de y code> n'est pas terminé par NULL.
SHLEN () CODE> compte les caractères jusqu'à ce qu'il frappe un caractère nul. Le vôtre est arrivé à en trouver un après 6 ans, mais cela pourrait être n'importe quel nombre. Essayez ceci:
CHAR Y [] = {'T', 'E', 'S', 'T', 'T', '\ 0'}; CODE> P>
SHLEN () code> pourrait ressembler (en haut de ma tête - ne pas avoir mon livre K & R Handy, mais je crois qu'il y a une implémentation donnée là-bas): p>
size_t strlen(const char* s)
{
size_t result = 0;
while (*s++) ++result;
return result;
}
Alors, Strlen vient de renvoyer le pointeur jusqu'à ce qu'il trouve une autre \ 0 partout où elle peut?
@Learningc: Exactement. Il continue d'incrémenter le pointeur et de regarder ce qui est là. Quand il trouve un zéro, il arrête et retourne combien de caractères il a examiné (à l'exclusion du zéro).
@Learningc: oui. Ou jusqu'à ce qu'il se bloque avec un segfault à la place. Ou jusqu'à ce qu'il format votre disque dur. Le comportement est non défini i> si votre entrée n'est pas terminée de zéro. n'importe quoi i> peut arriver.
Andreyt est correct. En pratique, cela trouvera souvent une null avant tout ce qui ne se produit. Mais vous ne pouvez jamais être sûr. Je doute que cela formaterait déjà votre disque dur, mais vous pourriez certainement partir dans la mémoire interdite et avoir une défaillance de segmentation.
@Fred: En fait, quelque chose de mauvais arrive le moment même sur l'octet sur l'octet où le null aurait dû être. Depuis (en supposant des entiers 8 bits), les chances d'un octet nul étant là-bas n'est pas tout ce qui va beaucoup mieux que 1/256, dans la pratique, quelque chose de mauvais arrive assez souvent.
@Fred avant les jours de la mémoire protégée, cela pourrait réellement endommager votre matériel. Certaines choses ont été cartographiées dans la mémoire et si une valeur a été lue de certaines adresses, elle a modifié l'état de l'appareil, éventuellement la mettre dans un état non valide ..
@sbi: Si vous voulez dire que le mauvais résultat est "quelque chose de mauvais", vous avez raison. Bon point. Mon sens était une chose encore pire que celle-là (crash, etc.) @earlz: Bien sûr, mais je pense que c'est plutôt rare ces jours-ci.
Question: Si vous aviez à droite une meilleure copie de chaîne Comment pourriez-vous être sûr que la chaîne passée à être copiée avait un \ 0. Comme vous ne pouviez pas trouver la longueur de cette "chaîne", vous ne pouviez pas demander si String [Lastchar] == '\ 0'.
@Learningc: ce serait une exigence sur l'appelant de votre fonction que la chaîne soit terminée, tout comme une exigence sur l'appelant de Strlen code> ou
strcpy code> que l'entrée est une chaîne à peine terminée.
Ce n'est pas une chaîne de terminaison zéro em>. C'est un tableau de quatre caractères, Vous pouvez éviter cela en utilisant la syntaxe spéciale pour l'initialisation de la matrice de caractères: p> ceci initialise BTW, voici un simple '\ 0' code>.
SHLEN () CODE> compte simplement les caractères jusqu'à ce qu'il frappe un zéro. Avec
y code>, il compte simplement sur la fin de la matrice jusqu'à ce qu'il trouve accidentellement un octet zéro.
Faire cela, vous invoquez un comportement non défini. Le code pourrait aussi bien formater votre disque dur. p> y code> avec cinq caractères em> strong>, puisqu'il ajoute automatiquement un
'\ 0' code>.
Notez que j'ai aussi quitté la taille de la matrice non spécifiée. Le compilateur figure cela en elle-même, et il reporte automatiquement si je change la longueur de la chaîne. p> SHLEN () code> Mise en œuvre: p>
size_t strlen(const char* p)
{
size_t result = 0;
while(*p++) ++result;
return result;
}
Wow, je n'ai pas vu votre Strlen () code> Avant d'ajouter le mien. Ils sont identiques! Grands esprits ... 8v)
La source GNU LIBC pour les fonctions de chaîne est assez éclairée de fouiller dans, et étonnamment complexe.
@Fred: Eh bien, c'est l'un des algorithmes les plus fondamentaux de la bibliothèque C et c'est un excellent exemple en K & R. Pas étonnant que la plupart d'entre nous l'avons imprimé dans leur mémoire.
Ce qui suit n'est pas un réseau NULL terminé de caractères:
char y[4] = {'t','e','s','t'};
char *x = "test";
Aux fins du SHLEN () code>, oui. Cependant,
y code> est une matrice de cinq
char code> et son contenu peut être modifié à volonté.
x code> est un pointeur sur
char code>, et dans ce cas indique une chaîne qui ne peut pas être modifiée de manière fiable. D'autre part, il est possible de réaffecter une valeur à
x code> mais pas à
y code>.
@David Thornley La réponse a été donnée dans un contexte débutant juste pour illustrer ce qui s'est mal passé en fonction de l'OP. Maintenant, de meilleures réponses ont été données. Pas besoin de bowervote
IME exactement des différences aussi subtiles que celle-ci ( x [0] = 'x'; code> est bien lorsque vous avez dit
char x [] = "x"; code>, mais fatal quand Vous dites
char * x = "x"; code>) ne peut jamais être trop stressé, surtout pour les débutants.
Votre Votre SHLEN code> fonctionne avec strings em>. La chaîne est définie comme une séquence (tableau) de caractères terminée avec
\ 0 code> caractère. P>
x code> pointe vers une chaîne. Donc,
SHLEN code> fonctionne bien avec
x code> comme argument. P>
y code> n'est pas une chaîne. Pour cette raison, passez
Y code> à
SHLEN code> entraîne un comportement non défini. Le résultat n'a pas de sens et imprévisible. P>
Une chaîne de type C réelle est une plus grande que le nombre de ses caractères, car il a besoin d'un caractère null de terminaison. P>
Par conséquent, CHAR Y [4] = {'T', 'E', 'S', 'T', 'T'}; code> ne forme pas une chaîne, car il s'agit de quatre caractères.
char y [] = "test"; code> ou
char y [5] = "test"; code> formerait une chaîne, car ils auraient une matrice de caractère de cinq caractères. se terminant par le terminateur null-octet. P>
Comme d'autres l'ont dit, vous devez simplement vous assurer de mettre fin à une chaîne avec le caractère 0 ou '\ 0'. À titre de note latérale, vous pouvez vérifier cela: http://bstring.sourceforge.net/ . Il a une fonction de longueur de chaîne O (1), contrairement à la charogne C / C ++ qui est sujette d'erreur et lente à O (n), où n est le nombre de caractères non nuls. Je ne me souviens pas de la dernière fois que j'ai utilisé Strlen et c'est des amis. Optez pour des fonctions / classes sécurisées et rapides! P>
Lorsque vous utilisez les guillemets simples, utilisez toujours '/ 0' mais dans des devis doubles évitent d'utiliser le '/ 0' dans SHLEN () P>
Notez que la fonction SHLEN () ne compose pas le caractère nul \ 0 tout en calculant la longueur p>
Oui, c'était juste une coïncidence.
En dehors des réponses (qui sont excellentes si un peu répétitif), je voudrais souligner que, tandis que
"test" code> est une syntaxe pratique pour la séquence
't', 'e' ", s ',' t ', 0 code>, vous pouvez en fait en tant que cas particulier initialiser un tableau de caractères avec
char y [4] = "test"; code> auquel cas la finale 0 Être omis (il n'y a tout simplement pas de place à celui-ci dans
y code>).