Question

J'essaie toujours d'éviter de renvoyer des littéraux de chaîne, car je crains qu'ils ne soient définis en dehors de la fonction. Mais je ne suis pas sûr que ce soit le cas. Prenons, par exemple, cette fonction:


const char *
return_a_string(void)
{
    return "blah";
}

Ce code est-il correct? Cela fonctionne pour moi, mais peut-être que cela ne fonctionne que pour mon compilateur (gcc). La question est donc de savoir si les littéraux (chaîne) ont une portée ou s'ils sont présents / définis tout le temps.

Était-ce utile?

La solution

Ce code convient à toutes les plateformes. La chaîne est compilée dans le binaire en tant que littéral de chaîne statique. Si vous êtes sur Windows par exemple, vous pouvez même ouvrir votre fichier .exe avec le bloc-notes et rechercher la chaîne elle-même.

Puisqu'il s'agit d'une chaîne littérale statique, la portée n'a pas d'importance.

Regroupement de chaînes:

Une chose à surveiller est que, dans certains cas, des littéraux de chaîne identiques peuvent être "groupés". pour économiser de l'espace dans le fichier exécutable. Dans ce cas, chaque chaîne littérale identique pourrait avoir la même adresse mémoire. Vous ne devez jamais présumer que ce sera ou ne sera pas le cas cependant.

Dans la plupart des compilateurs, vous pouvez choisir d'utiliser ou non le regroupement statique de chaînes pour mélanger les littéraux.

Taille maximale des littéraux de chaîne:

Plusieurs compilateurs ont une taille maximale pour le littéral chaîne. Par exemple, avec VC ++, cela représente environ 2 048 octets.

La modification d'un littéral de chaîne donne un comportement non défini:

Il ne faut jamais modifier un littéral de chaîne. Son comportement est indéfini.

char * sz = "this is a test";
sz[0] = 'T'; //<--- undefined results

Littéraux de chaîne larges:

Tout ce qui précède s'applique également aux littéraux de chaîne large.

Exemple: L "il s'agit d'un littéral de chaîne large";

La norme C ++ indique: (section lex.string)

  

1 Un littéral de chaîne est une séquence   de caractères (tels que définis dans    lex.ccon ) entourée de guillemets, commençant éventuellement par le   lettre L, comme dans "..." ou L "...". Un littéral de chaîne qui ne commence pas   avec L est un littéral de chaîne ordinaire, également appelé étroit   chaîne littérale. Un littéral de chaîne ordinaire a le type "tableau de n   const   char " et la durée de stockage statique ( basic.stc ), où n est le   Taille   de la chaîne telle que définie ci-dessous, et est initialisée avec le   personnages. Un littéral de chaîne commençant par L, tel que L "asdf",   est   une large chaîne littérale. Un littéral de chaîne large a le type "tableau de   n   const wchar_t " et a une durée de stockage statique, où n est la taille   de   la chaîne telle que définie ci-dessous, et est initialisée avec le caractère donné   ters.

     

2 Si tous les littéraux de chaîne sont distincts (c'est-à-dire, sont stockés dans     non-chevauchement) est défini par la mise en oeuvre. L'effet   de    tenter de modifier un littéral de chaîne n’est pas défini.

Autres conseils

Je vous donne un exemple pour que votre confusion devienne un peu claire

char *f()
{
char a[]="SUMIT";
return a;
}

cela ne fonctionnera pas.

mais

char *f()
{
char *a="SUMIT";
return a;
}

cela fonctionne.

Raison: " SUMIT " est un littéral qui a une portée globale. tandis que le tableau qui est juste une séquence de caractères {'S', 'U', 'M', 'I', "T" '\ 0'} a une portée limitée et disparaît dès que le programme est renvoyé.

J'espère que cela vous aidera

Ceci est valable en C (ou C ++), comme d'autres l'ont expliqué.

La seule chose à laquelle je puisse penser est que si vous utilisez des dll, le pointeur ne restera pas valide si la dll contenant ce code est déchargée.

Le standard C (ou C ++) ne comprend ni ne prend en compte le code de chargement et de déchargement au moment de l'exécution. Par conséquent, tout ce qui en résultera aura des conséquences définies par l'implémentation: dans ce cas, le littéral chaîne, qui est supposé avoir une durée de stockage statique, il ressort du POV du code appelant qu'il ne persiste pas pendant toute la durée du programme.

Oui, ça va. Ils vivent dans une table de chaînes globale.

Non, les littéraux de chaîne n'ayant pas de portée, votre code est garanti pour fonctionner sur toutes les plates-formes et les compilateurs. Ils sont stockés dans l'image binaire de votre programme, vous pouvez donc toujours y accéder. Cependant, essayer de leur écrire (en supprimant const ) entraînera un comportement indéfini.

Vous renvoyez en fait un pointeur sur la chaîne terminée par un zéro stockée dans la section de données de l'exécutable, une zone chargée lorsque vous chargez le programme. Évitez simplement d'essayer de changer les caractères, cela pourrait donner des résultats imprévisibles ...

Il est vraiment important de noter les résultats non définis mentionnés par Brian. Puisque vous avez déclaré que la fonction renvoyait un type const char *, tout devrait bien se passer, mais sur de nombreuses plateformes, les littéraux de chaîne sont placés dans un segment en lecture seule de l'exécutable (généralement le segment de texte) et leur modification entraînera une violation d'accès. sur la plupart des plates-formes.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top