web-dev-qa-db-fra.com

Est-il mauvais de déclarer une chaîne de style C sans const? Si oui, pourquoi?

Faire cela en C++

char* cool = "cool";

compile bien, mais me donne un avertissement: 

Conversion obsolète de constante de chaîne en caractère *.

Je n'utiliserais jamais volontairement une chaîne de style C sur std::string, mais juste au cas où on me poserait cette question: 

est-ce une mauvaise pratique de déclarer une chaîne de style C sans le modificateur const? Si oui, pourquoi?

63
Coffee Maker

Oui, cette déclaration est une mauvaise pratique, car elle permet de nombreuses manières de provoquer accidentellement un comportement indéfini en écrivant dans un littéral de chaîne, notamment:

cool[0] = 'k';
strcpy(cool, "oops");

D'un autre côté, c'est parfait, car cela alloue un tableau de caractères non const:

char cool[] = "cool";
59
aschepler

Oui, en C++, vous devez toujours faire référence aux littéraux de chaîne avec des variables de type const char * ou const char [N]. C'est également une bonne pratique lors de l'écriture de nouveau code C.

Les littéraux de chaîne sont stockés dans la mémoire en lecture seule, lorsque cela est possible; leur type est correctement qualifié const-. C, mais pas C++, inclut une logique de compatibilité ascendante dans laquelle le compilateur leur donne le type char [N] même si ils sont stockés dans une mémoire en lecture seule. En effet, les littéraux de chaîne sont plus anciens que le qualificateur const. const a été inventé dans la période qui a précédé ce qu'on appelle maintenant "C89" - l'ancienne forme "K & R" du langage ne l'avait pas.

Certains compilateurs C incluent un mode facultatif dans lequel la verrue à compatibilité ascendante est désactivée et char *foo = "..."; vous donnera le même diagnostic ou un diagnostic similaire qu’il fonctionne en C++. GCC épelle ce mode -Wwrite-strings. Je le recommande fortement pour le nouveau code; Cependant, l'activer pour l'ancien code est susceptible de nécessiter une énorme quantité de travail sans grand bénéfice.

16
zwol

C'est mauvais. C'est tres mal. Au point que cela n’est plus possible en C++ 11.

Modifier la mémoire d'un littéral est un comportement indéfini.

14
milleniumbug

Tout d'abord, char* cool = "cool"; n'est pas le C++ standard. Un littéral de chaîne a le type const char[n]. La ligne de code ci-dessus casse donc const-correct et ne doit pas être compilée. Certains compilateurs tels que GCC le permettent, mais émettent un avertissement, car il s'agit d'un blocage de C. MSVC émettra une erreur puisqu'il s'agit d'une erreur.

Deuxièmement, pourquoi ne pas laisser le compilateur travailler pour vous? Si elle est marquée const, vous obtiendrez une erreur du compilateur Nice si vous tentez accidentellement de la modifier. Si vous ne le faites pas, vous pouvez obtenir une erreur de temps d'exécution vraiment désagréable qui peut être beaucoup plus difficile à trouver.

13
NathanOliver

C'est mauvais parce que les constantes de chaîne peuvent être contenues une seule fois par binaire (mot-clé: stringtable, .strtab). Par exemple. dans

char *cool = "cool";
char *nothot = "cool";

les deux variables peuvent pointer vers le même emplacement mémoire. La modification du contenu de l’un d’eux peut également altérer l’autre, de sorte qu’après

strcpy(nothot, "warm");

votre cool devient "chaud".

En bref, c'est un comportement indéfini.

7
ensc

Il s'agit d'un littéral de chaîne, il doit donc être constant car la mémoire peut être située dans la section lecture seule. Si vous avez char cool[] = "cool"; alors ce n’est pas un problème, la mémoire vous appartient.

6
KIIV

char * cool = "cool" 

"cool" sera stocké dans un bloc en lecture seule (généralement dans un segment de données) partagé entre les fonctions. Si vous essayez de modifier la chaîne "cool" par le point cool, vous obtiendrez une erreur telle qu'une erreur de segment lorsque le programme est en cours d'exécution. Si vous utilisez const char* cool = "cool", vous obtiendrez une erreur lors de la compilation si vous essayez de modifier la chaîne.
Vous pouvez lire cette page pour plus d’informations http://www.geeksforgeeks.org/storage-for-strings-in-c/

2
zhangke

C'est une bonne pratique d'écrire const pour les chaînes (en particulier lorsque vous utilisez un littéral de chaîne), mais en C cela ne fait guère de différence, cela vous enverra un avertissement en c ++ mais aucun avertissement en c, souvenez-vous également que certains compilateurs supposent une extension .c comme c mais .c comme c ++, faites donc attention à ces points. Sinon, c'est une bonne pratique d'utiliser const avec la casse des chaînes, aussi vous ne changez pas la chaîne par erreur ou essayez de changer un littéral de chaîne stocké. en lecture seule.

0
Noshiii