2016-02-18 2 views
2

Voici mon code:strlen comportement de fonction sur un seul caractère

void func(char c) 
{ 
    char * ptr = &c; 
    size_t len = strlen(ptr); 
    printf("len - %d\n", len); 
} 

len est toujours imprimé comme 1.

strlen(..) détermine la longueur d'un tableau char en trouvant le caractère nul (\0) au fin de celui-ci. Ici ptr est initialisé avec juste l'adresse d'un seul caractère (c). c ne contient aucun caractère nul. Comment est-ce queobtient la longueur?

+2

"Mon code a un bug, pourquoi fait-il quelque chose d'étrange?" Eh bien, parce qu'il a un bug. Corrige le bug et le mystère s'en ira. –

+0

'J'ai fait une mauvaise chose. Je sais que j'ai fait une mauvaise chose. De mauvaises choses sont arrivées en conséquence. Expliquer pourquoi'. Avoir un downvote :( –

Répondre

7

Vous ne pouvez pas utiliser strlen() sur un pointeur qui ne pointe pas vers un tableau à terminaison nulle. Il appelle undefined behavior. Une fois que votre programme atteint UB, rien n'est garanti.

FWIW, strlen() renvoie un type size_t, vous devez donc utiliser le spécificateur de format %zu pour imprimer le résultat.

+1

Le spécificateur de format doit être '% zu'. – haccks

+0

@haccks abosolutely, mis à jour. :) –

4

Le comportement de votre code est undefined pour deux raisons. Il renvoie 1 par accident.

  1. strlen travaux en commençant à une adresse donnée, et incrémenter cette adresse jusqu'à \0 soit atteinte. Ceci est cohérent avec la façon dont la bibliothèque standard C modélise les chaînes. Si vous ne possédez pas toute la mémoire (en tant que bloc contigu) entre l'adresse de départ et celle \0, l'entrée vers strlen est incorrecte.

  2. Le comportement de printf est indéfini en raison d'un spécificateur de format incorrect. Utilisez %zu pour size_t.

0

c ne contient pas de caractères nuls. Comment ptr obtient-il la longueur?

Ce n'est pas le cas. Il semble donner la bonne réponse dans vos tests parce que l'emplacement de mémoire suivant l'adresse de c arrive à contenir un zéro octet. Cet emplacement n'est pas défini pour contenir un zéro, et le programme n'est pas autorisé à y accéder, vous ne pouvez donc pas compter sur un tel code pour continuer à fonctionner.

Dans la langue de la norme C, le comportement du programme est non défini, ce qui signifie que non seulement le résultat de l'opération imprévisible, the entire program is rendered meaningless.

Même sans prendre en compte le comportement non défini, ci-dessus le code peut cesser de fonctionner avec le moindre changement - par exemple, lorsque vous changez d'architecture, de compilateur ou même de drapeaux de compilation, ou lorsque vous ajoutez plus de fonctions dans le mixage. Bien que ces extraits de code peuvent être utiles pour apprendre comment les choses fonctionnent sous le capot, elles ne devraient jamais être utilisées dans le code de production.