8
votes

Est le: "std :: string peut tenir" \ 0 "caractère" par design?

Le fait que std :: string peut réellement contenir '\ 0' les caractères apparaît tout le temps. Ceci est bien sûr incompatible avec les chaînes de style C.

Je me demande donc, est-ce par conception, ou est-ce une omission, ou est-ce que ce n'est que le fait que la norme n'interdit pas cela et que les compilateurs permettent que cela se produise?


2 commentaires

Je dirais que les chaînes de style C sont incompatibles avec la «chaîne». '\ 0' est un caractère valide et l'utilisant en tant que terminateur entraîne le comportement Bizzare d'un tableau d'éléments où une valeur particulière d'un ensemble de 256 est exclue. Personnellement, je pense que l'utilisation du terminateur NULL est responsable de l'utilisation de scripts Bash interprétés à base de textes lents pour 99,9% des "applications" U ** X - Les développeurs ont peur d'utiliser du code compilé au cas où leurs cordes sont terminées tôt par nulls dans les données


@Martin: Droit sur. pas Permettre à un caractère arbitraire est l'ennemi, pas l'inverse.


5 Réponses :


1
votes

La norme ne dit pas que dans le cas d'une STD :: chaîne '\ 0' est un caractère spécial. Par conséquent, toute implémentation complitive de std :: string ne doit pas traiter '\ 0' comme n'importe quel caractère spécial. Sauf si bien sûr un Const Char * est transmis à une fonction de membre d'une chaîne, supposée être dénoncée null.


0 commentaires

3
votes

Il existe un ensemble de fonctions qui acceptent des arguments "char *" et supposent que la chaîne est terminée par un zéro. Si vous les utilisez soigneusement, vous pouvez certainement avoir des chaînes avec 0 en eux.

Les cordes STL, en revanche, autorisent intentionnellement zéro octets, car ils n'utilisent pas 0 pour la résiliation. La réponse simple à votre question est donc: «Oui, par design. '


1 commentaires

Mais ... une chaîne de terminaison nulle est une chaîne de style C. Ou un C-String , si vous voulez. Bien sûr, un Char * dans C peut pointer sur un tampon qui inclut des nottes nulltes, mais ce tampon ne peut pas être appelé une chaîne C.



13
votes

Je me demande quelle est votre querelle. '\ 0' est juste un autre caractère. Il n'y a pas de moyen efficace de lui interdire dans une chaîne de caractère générale. Que le même personnage a une signification particulière dans C est malheureux, mais doit être traitée comme chaque restriction imposée par le code hérité dès que vous interagez avec cela.

Cela ne devrait pas être un problème aussi longtemps que vous vous tenez au code qui utilise std :: string exclusivement.

Pour résoudre votre commentaire, nous devons consulter le constructeur qui prend un char * qui serait basic_string (const graphique * s, const allocator & a = allocator ()) Dans 21.4.2 9/10 dans N3242. Il est indiqué que la taille de la chaîne interne est déterminée par traits :: longueur (s) qui dans le cas de std :: string est SHLEN ce qui nécessite que son argument soit résilié par NULL. Donc, oui, si vous essayez de construire un std :: string à partir d'un const char * il doit être résilié null.


3 commentaires

Je pense que je n'ai pas vraiment souligné cela correctement. Je suppose que ce que je demande est de savoir si std :: string fonctionne avec des chaînes terminées (ne doit pas être terminée de Nul) ou ne se soucie tout simplement pas.


De plus, la fonction c_str () génère une chaîne terminée nulle, où NULL est le résultat d'une initialisation de la valeur quelconque le type de caractère est.


@Potatoswatter qui est un peu l'abstraction de l'ensemble de la corde NULL terminée. N'en avez jamais pensé de cette façon.



1
votes

par la conception.

C peut aussi ne pas avoir NULL NULL Strings terminés: P>

struct String {
  char *str;
  size_t length;
  size_t capacity;
};


3 commentaires

Voir le Mother String Library pour C, d'autres pensent à ce sujet :)


Cela dit, strncpy et strncat sera ajouter un terminateur null s'il y a de la place.


@Kerreksb Ces fonctions sont différentes. Voir ma réponse.



0
votes

strncpy vs. code> strncat

Cela dit, Strncpy et Strncat, etc., appendez un terminateur nul s'il y a de la place.

En réalité strncpy et strncat sont très différents:

strncpy écrit une "chaîne n-bytes remplie nul" à un n -bytes tampon: une chaîne dont la longueur l est < fort> au plus n , tel que le dernier n - l les octets sont remplis de nul. Notez le pluriel: Tous les derniers octets sont mis à zéro, notez une seule. Notez également le fait que la valeur maximale autorisée pour l est vraiment n , il peut donc y avoir zéro nul octets: le tampon peut ne pas contenir une chaîne de terminaison Nul. (GCC a une fonction non portable pour mesurer une telle "chaîne N-Bytes remplie nul": strnlen .)

au contraire, STRNCAT sortira une chaîne à résiliation nul sur un tampon. Dans les deux cas, la chaîne est tronquée si elle est trop longue, mais dans le cas de Strncpy , une chaîne de lettres n ira dans un n -Byle tampon, alors que dans le cas de strncat , résultat de n les lettres ne correspondra que dans ( n +1)-buffer .

Cette différence provoque beaucoup de confusion aux débutants C et même non débutants. J'ai même vu des cours et des livres qui enseignent "la programmation C Safe C" qui avait confondu et contredire des informations sur ces fonctions standard.

Ces fonctions de manipulation de chaîne «Safe» C (Safe »(le« STRN * «La famille) ont été très critiquées dans la communauté C« Secure Programming »et mieux conçue (mais non standard. ) Les alternatives ont été inventées (notamment le " strl * " famille: strlcpy ...).

Résumé:

  • strncpy ajoutera un terminateur null s'il y a de la place ;
  • strncat ajoutera un terminateur null toujours .


0 commentaires