54 votes

Pourquoi les littéraux de chaîne (char*) en C++ doivent-ils être constants ?

J'ai récemment appris le C++ et j'ai réalisé que les littéraux de chaînes en C++ doivent être constants, alors qu'en C, ce n'est pas le cas. Voici un exemple. Le code suivant serait valide en C, mais pas en C++:

 char* str = "Hello, World!"; 

Pour faire la même chose en C++, l'instruction suivante doit être utilisée:

 const char* str = "Hello, World!"; 

Pourquoi y a-t-il une différence?

26 votes

Alors qu'en C, ce n'est pas le cas Vous avez tort. Les littéraux de chaîne en C sont constants, mais ils peuvent être pointés par un char*. Vous ne pouvez toujours pas modifier la chaîne via ce pointeur. En C++, ils ont simplement éliminé cette exception à la const-correctness pour éviter la confusion et les erreurs.

5 votes

Parce que c'est ainsi qu'ils ont conçu le langage. C n'avait pas initialement le mot-clé const, donc cela casserait du code hérité s'ils changeaient les littéraux pour nécessiter une qualification const après l'introduction du mot-clé. Les littéraux de chaîne de C sont immuables, cependant, donc changer le contenu est un comportement non défini même s'il n'est pas qualifié de const.

0 votes

@ChristianGibbons alors pourquoi le code suivant fonctionne-t-il ? ``char* str = "Hello World"; str = "Goodbye World";```

46voto

John Bode Points 33046

En ajoutant un peu à la réponse de Christian Gibbons...

En C, les littéraux de chaîne, comme "Bonjour tout le monde!", sont stockés dans des tableaux de char de sorte qu'ils sont visibles pendant toute la durée de vie du programme. Les littéraux de chaîne sont censés être immuables, et certaines implémentations les stockeront dans un segment de mémoire en lecture seule (de sorte que toute tentative de modifier le contenu du littéral déclenchera une erreur d'exécution). Certaines implémentations ne le font pas, et tenter de modifier le contenu du littéral peut ne pas déclencher d'erreur d'exécution (cela peut même sembler fonctionner comme prévu). La définition du langage C laisse le comportement "indéfini" afin que le compilateur soit libre de gérer la situation comme il le souhaite.

En C++, les littéraux de chaîne sont stockés dans des tableaux de _const_ char, de sorte que toute tentative de modifier le contenu du littéral déclenchera un diagnostic au moment de la compilation.

Comme le souligne Christian, le mot clé const n'était pas à l'origine une partie de C. Il faisait cependant initialement partie de C++, et il rend l'utilisation des littéraux de chaîne un peu plus sûre.

Rappelez-vous que le mot clé const ne signifie pas "stocker ceci dans une mémoire en lecture seule", cela signifie seulement "cette chose ne peut pas être la cible d'une assignation".

Rappelez-vous également que, à moins qu'il ne soit l'opérande des opérateurs sizeof ou unaire *, ou qu'il ne s'agisse d'un littéral de chaîne utilisé pour initialiser un tableau de caractères dans une déclaration, une expression de type "tableau de N éléments de T" sera convertie ("déclinée") en une expression de type "pointeur vers T" et la valeur de l'expression sera l'adresse du premier élément du tableau.

En C++, lorsque vous écrivez

const char *str = "Bonjour tout le monde";

l'adresse du premier caractère de la chaîne est stockée dans str. Vous pouvez faire en sorte que str pointe vers un autre littéral de chaîne :

str = "Adieu monde cruel";

mais ce que vous ne pouvez pas faire, c'est modifier le contenu de la chaîne, quelque chose comme

str[0] = 'h';

ou

strcpy( str, "Quelque chose d'autre" );

1 votes

IMO une réponse correcte. Je soulignerais probablement plus que dans const char *s="foo"; le const ne concerne que le pointeur (ne peut pas être utilisé en écriture), mais ne dit rien sur l'objet pointé. Malheureusement, beaucoup de programmeurs C++ (et même la bibliothèque standard) confondent les deux, notamment avec les références (c'est-à-dire que dans const X& x le mot-clé const est relatif à la référence seulement et ne dit rien sur l'objet référencé; passer une const& n'est pas une façon intelligente de passer par valeur car vous pouvez rencontrer des problèmes de durée de vie ou d'aliasing).

1 votes

@6502: const char *str signifie que l'objet pointé est const, pas le pointeur. Nous pouvons écrire une nouvelle valeur à str (le pointer vers un objet différent), mais pas à *str ou str[i]. char * const str signifie que le pointeur lui-même est const et ne peut pas être modifié, mais la chose à laquelle il pointe peut l'être.

0 votes

Non. La déclaration const char *str; est une déclaration d'un "pointeur en lecture seule" , c'est-à-dire un pointeur qui ne peut être utilisé que pour la lecture... mais c'est une propriété du pointeur, cela ne dit rien sur la constance de l'objet pointé. L'objet pointé peut changer, simplement il ne peut pas être changé en utilisant ce pointeur (mais il peut y avoir par exemple d'autres pointeurs en lecture/écriture vers le même objet). Un const char * n'est pas un pointeur vers un char qui est constant, c'est un pointeur vers un char qui ne peut pas être utilisé pour l'écriture.

28voto

Christian Gibbons Points 2416

C n'avait initialement pas le mot-clé const, donc il aurait cassé du code hérité s'ils avaient changé les littéraux pour exiger une qualification const après l'introduction du mot-clé. Les littéraux de chaîne de C sont immuables, cependant, donc changer le contenu est un comportement indéfini même s'ils ne sont pas qualifiés const.

En revanche, C++ a été conçu avec le mot-clé const. Initialement, C++ permettait aux littéraux de chaîne d'être assignés à des char * non qualifiés const probablement pour la compatibilité avec le code C existant. Cependant, à partir de la norme C++03, ils ont décidé de déprécier cette fonctionnalité plutôt que de permettre la dissonance de continuer éternellement. Je supposerais que la quantité de code C++ hérité comptant sur des char * non qualifiés const pointant vers des littéraux de chaîne est suffisamment petite pour que cela en vaille la peine.

9 votes

Notez que C++ autorisait initialement les char* non constants pour les littéraux. Mais cela a été déprécié et officiellement supprimé en C++11. Donc même si C++ a été initialement conçu avec le const à l'esprit, cette exception à la règle a persisté pendant un certain temps.

0 votes

Oui, ce n’est qu’à partir de C++03 que ce comportement a été déprécié.

0 votes

Hmm, d'accord, je vais essayer de trouver les meilleurs mots pour corriger l'angle de réponse en C++.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X