web-dev-qa-db-fra.com

Quel est le type de littéraux de chaîne en C et C ++?

Quel est le type de chaîne littérale en C? Est-ce char * ou const char * ou const char * const?

Et C++?

61
missingfaktor

En C, le type d'un littéral de chaîne est un char[] - ce n'est pas const selon le type, mais c'est un comportement indéfini de modifier le contenu. En outre, 2 littéraux de chaîne différents qui ont le même contenu (ou suffisamment de même contenu) peuvent ou non partager les mêmes éléments du tableau.

De la norme C99 6.4.5/5 "Littéraux à cordes - Sémantique":

Dans la phase de traduction 7, un octet ou un code de valeur zéro est ajouté à chaque séquence de caractères multi-octets qui résulte d'un ou plusieurs littéraux de chaîne. La séquence de caractères multi-octets est ensuite utilisée pour initialiser un tableau de durée et de longueur de stockage statique juste suffisant pour contenir la séquence. Pour les littéraux de chaîne de caractères, les éléments du tableau ont le type char et sont initialisés avec les octets individuels de la séquence de caractères multi-octets; pour les littéraux de chaîne large, les éléments du tableau ont le type wchar_t, et sont initialisés avec la séquence de caractères larges ...

Il n'est pas précisé si ces tableaux sont distincts à condition que leurs éléments aient les valeurs appropriées. Si le programme tente de modifier un tel tableau, le comportement n'est pas défini.

En C++, "Un littéral de chaîne ordinaire a le type 'tableau de n const char '"(à partir de 2.13.4/1" Littéraux de chaîne "). Mais il existe un cas particulier dans la norme C++ qui permet au pointeur vers les littéraux de chaîne de se convertir facilement en pointeurs non qualifiés (4.2/2" Tableau vers conversion du pointeur "):

Un littéral de chaîne (2.13.4) qui n'est pas un littéral de chaîne large peut être converti en une valeur r de type "pointeur vers char"; un littéral de chaîne large peut être converti en une valeur r de type "pointeur vers wchar_t".

En guise de remarque - parce que les tableaux en C/C++ se convertissent si facilement en pointeurs, un littéral de chaîne peut souvent être utilisé dans un contexte de pointeur, tout comme n'importe quel tableau en C/C++.


Éditorialisation supplémentaire: ce qui suit est en fait surtout de la spéculation de ma part sur la justification des choix effectués par les normes C et C++ concernant les types littéraux de chaînes. Alors prenez-le avec un grain de sel (mais veuillez commenter si vous avez des corrections ou des détails supplémentaires):

Je pense que la norme C a choisi de créer des types de chaîne non const constants car il y avait (et il y a) tellement de code qui s'attend à pouvoir utiliser des pointeurs char non qualifiés de const qui pointent vers des littéraux. Lorsque le qualificatif const a été ajouté (ce qui, si je ne me trompe pas, a été fait autour du temps de normalisation ANSI, mais longtemps après que K&R C ait été là pour accumuler une tonne de code existant) s'ils ont fait des pointeurs vers des littéraux de chaîne uniquement pouvant être affecté à char const* types sans distribution presque tous les programmes existants auraient dû être modifiés. Pas un bon moyen de faire accepter un standard ...

Je crois que le changement en C++ selon lequel les littéraux de chaîne sont qualifiés par const a été effectué principalement pour permettre à une chaîne littérale de correspondre de manière plus appropriée à une surcharge qui prend un "char const* ". Je pense qu'il y avait aussi un désir de fermer un trou perçu dans le système de type, mais le trou a été largement rouvert par le cas spécial dans les conversions tableau-pointeur.

L'annexe D de la norme indique que la "conversion implicite de la qualification const en non-const pour les littéraux de chaîne (4.2) est déconseillée", mais je pense que tant de code se briserait encore qu'il faudra beaucoup de temps avant que les implémenteurs du compilateur ou le Le comité des normes est prêt à retirer le bouchon (à moins qu'une autre technique intelligente ne puisse être imaginée - mais le trou serait de retour, n'est-ce pas?).

59
Michael Burr

Un littéral de chaîne C a le type char [n]n est égal au nombre de caractères + 1 pour tenir compte du zéro implicite à la fin de la chaîne.

Le tableau sera alloué statiquement; ce n'est pas const, mais le modifier est un comportement non défini.

S'il avait le type de pointeur char * ou type incomplet char [], sizeof n'a pas pu fonctionner comme prévu.

Faire des littéraux chaîne const est un idiome C++ et ne fait partie d'aucune norme C.

10
Christoph

Pour diverses raisons historiques, les littéraux de chaîne étaient toujours de type char[] en C.

Au début (en C90), il a été déclaré que la modification d'un littéral de chaîne invoque un comportement indéfini.

Cependant, ils n'ont pas interdit de telles modifications, ni fait des littéraux de chaîne const char[] ce qui aurait été plus logique. C'était pour des raisons de rétrocompatibilité avec l'ancien code. Certains anciens systèmes d'exploitation (notamment DOS) ne protestaient pas si vous modifiiez les littéraux de chaîne, donc il y avait beaucoup de code autour.

C a encore ce défaut aujourd'hui, même dans la norme C la plus récente.

C++ a hérité du même défaut de C, mais dans les normes C++ ultérieures, ils ont finalement rendu les littéraux de chaîne const (marqués obsolètes en C++ 03, définitivement corrigés en C++ 11).

1
Lundin

Ils étaient de type char[]. Maintenant, ils sont de type const char[].

0
0xfe