Pourquoi les chaînes en C doivent-elles être terminées par zéro?

Je me demande juste pourquoi c‘est le cas. Je suis désireux d’en savoir plus sur les langages de bas niveau, et je suis seulement dans les bases du C, ce qui me confond déjà.

Est-ce que des langages comme PHP annulent automatiquement les chaînes lorsqu’elles sont interprétées et / ou analysées?

    De l’excellent article de Joel sur le sujet:

    Rappelez-vous la façon dont les chaînes fonctionnent en C: elles consistent en un groupe d’octets suivi d’un caractère nul, qui a la valeur 0. Cela a deux implications évidentes:

    Il n’existe aucun moyen de savoir où se termine la chaîne (c’est-à-dire la longueur de la chaîne) sans vous y déplacer, en recherchant le caractère nul à la fin. Votre chaîne ne peut contenir aucun zéros. Donc, vous ne pouvez pas stocker un blob binary arbitraire comme une image JPEG dans une chaîne C. Pourquoi les chaînes C fonctionnent-elles de cette façon? C’est parce que le microprocesseur PDP-7, sur lequel UNIX et le langage de programmation C ont été inventés, avait un type de chaîne ASCIZ. ASCIZ signifiait “ASCII avec un Z (zéro) à la fin”.

    Est-ce la seule façon de stocker des chaînes? Non, en fait, c’est l’une des pires façons de stocker des chaînes. Pour les programmes non sortingviaux, les API, les systèmes d’exploitation et les bibliothèques de classes, évitez les chaînes ASCIZ telles que peste.

    Les chaînes C sont des tableaux de caractères et un tableau C est simplement un pointeur sur un emplacement de mémoire, qui est l’emplacement de départ du tableau. Mais aussi la longueur (ou la fin) du tableau doit être exprimée d’une manière ou d’une autre; dans le cas de chaînes, une terminaison nulle est utilisée. Une autre solution consisterait en quelque sorte à porter la longueur de la chaîne à côté du pointeur de mémoire, ou à mettre la longueur à l’emplacement du premier tableau, ou à un autre endroit. C’est juste une question de convention.

    Les langages de niveau supérieur tels que Java ou PHP stockent les informations de taille avec le tableau automatiquement et de manière transparente, de sorte que l’utilisateur n’a pas à s’en soucier.

    Parce qu’en C, les chaînes ne sont qu’une séquence de caractères accédés par un pointeur sur le premier caractère.

    Il n’y a pas d’espace dans un pointeur pour stocker la longueur, vous avez donc besoin d’une indication de l’emplacement de la fin de la chaîne.

    En C, il a été décidé que cela serait indiqué par un caractère nul.

    En pascal, par exemple, la longueur d’une chaîne est enregistrée dans l’octet précédant immédiatement le pointeur, d’où la raison pour laquelle les chaînes pascal ont une longueur maximale de 255 caractères.

    C n’a pas de notion de chaînes par lui-même. Les chaînes sont simplement des tableaux de caractères (ou wchars pour Unicode et autres).

    En raison de ces faits, C n’a aucun moyen de vérifier la longueur de la chaîne, car il n’y a pas de “myssortingng-> length”, il n’y a pas de longueur définie quelque part. La seule façon de trouver la fin de la chaîne consiste à parcourir celle-ci et à rechercher le \ 0.

    Il existe des bibliothèques de chaînes pour C qui utilisent des structures telles que

    struct ssortingng { int length; char *data; }; 

    pour supprimer le besoin de la terminaison \ 0 mais ce n’est pas standard C.

    Les langages tels que C ++, PHP, Perl, etc. ont leurs propres bibliothèques de chaînes internes qui ont souvent un champ de longueur distinct qui accélère certaines fonctions de chaîne et supprime le besoin de \ 0.

    Certains autres langages (comme Pascal) utilisent un type de chaîne appelé (étonnamment) Pascal Ssortingng. Il stocke la longueur dans le premier octet de la chaîne, ce qui explique pourquoi ces chaînes sont limitées à une longueur de 255 caractères.

    Pensez à ce qu’est la mémoire: un bloc contigu d’unités de la taille en octets pouvant être remplies avec n’importe quel modèle de bits.

     2a c6 90 f6 

    Un personnage est simplement l’un de ces modèles de bits. Sa signification en tant que chaîne est déterminée par la façon dont vous la traitez. Si vous examiniez la même partie de la mémoire, mais en utilisant une vue entière (ou un autre type), vous obtiendriez une valeur différente.

    Si vous avez une variable qui est un pointeur vers le début d’un tas de caractères en mémoire, vous devez savoir quand cette chaîne se termine et le prochain élément de données (ou garbage) commence.

    Exemple

    Regardons cette chaîne en mémoire …

     H ello , world ! \0 ^ | +------ Pointer to ssortingng 

    … nous pouvons voir que la chaîne se termine logiquement après le ! personnage. S’il n’y avait pas de \0 (ou une autre méthode pour déterminer sa fin), comment pourrions-nous savoir, lorsque nous cherchons dans la mémoire, que nous avions fini avec cette chaîne? D’autres langues utilisent la longueur de chaîne avec le type de chaîne pour résoudre ce problème.

    J’ai posé cette question lorsque mes connaissances fondamentales en informatique étaient limitées et c’est la réponse qui aurait été utile il y a de nombreuses années. J’espère que cela aide aussi quelqu’un d’autre. 🙂

    C’est une convention – on aurait pu l’implémenter avec un autre algorithme (par exemple, la longueur au début du tampon).

    Dans un langage “de bas niveau” tel que l’assembleur, il est facile de tester efficacement “NULL”: cela pourrait faciliter la décision d’utiliser des chaînes terminées par NULL plutôt que de garder la trace d’un compteur de longueur.

    Ils doivent être annulés pour que vous sachiez combien de temps ils durent. Et oui, ils sont simplement des tableaux de char.

    Les langages de niveau supérieur tels que PHP peuvent choisir de vous cacher ou de ne pas l’utiliser du tout – ils peuvent par exemple conserver une longueur. C ne le fait pas de cette façon à cause des frais généraux impliqués. Les langages de haut niveau peuvent également ne pas implémenter de chaînes en tant que tableau de caractères – ils pourraient (et certains le font) les implémenter en tant que listes de tableaux de caractères, par exemple.

    En C, les chaînes sont représentées par un tableau de caractères alloué dans un bloc de mémoire contigu. Il doit donc exister un indicateur indiquant la fin du bloc (c.-à-d. Le caractère nul) ou un moyen de stocker la longueur (comme des chaînes Pascal). qui sont préfixés par une longueur).

    Dans des langages comme PHP, Perl, C #, etc., les chaînes peuvent avoir ou non des structures de données complexes, vous ne pouvez donc pas en déduire qu’elles ont un caractère nul. Par exemple, vous pourriez avoir un langage qui représente une chaîne comme ceci:

     class ssortingng { int length; char[] data; } 

    mais vous ne la voyez que comme une chaîne normale sans champ de longueur, car elle peut être calculée par l’environnement d’exécution de la langue et utilisée uniquement en interne par celle-ci pour allouer et accéder à la mémoire correctement.

    Elles sont terminées par zéro car de nombreuses fonctions de la bibliothèque standard les attendent.