2009-04-05 6 views
8

Je n'ai que peu de doutes sur les chaînes littérales en C++.Littéraux de chaînes

char *strPtr ="Hello" ; 
char strArray[] ="Hello"; 

Maintenant strPtr et strArray sont considérés comme des littéraux de chaîne. Selon ma compréhension, les littéraux de chaîne sont stockés dans la mémoire morte, donc nous ne pouvons pas modifier leurs valeurs.

Nous ne pouvons pas

strPtr[2] ='a'; 
and strArray[2]='a'; 

Les deux déclarations ci-dessus devraient être illégales. Le compilateur doit renvoyer des erreurs dans les deux cas.

Le compilateur conserve les littéraux en chaîne en lecture seule, donc si nous essayons de les modifier, le compilateur lance des erreurs.

Les données const sont également considérées comme étant en lecture seule.

Est-ce que les littéraux de chaîne et les données const sont traités de la même façon? Est-ce que je peux enlever la constance en utilisant const_cast de la chaîne littérale peut changer sa valeur?

Où exactement les littéraux de chaîne sont-ils stockés? (dans la section de données du programme)

Répondre

16

Maintenant strPtr et strArray sont considérés comme des littéraux de chaîne.

Non, ils ne le sont pas. Les littéraux de chaîne sont les éléments que vous voyez dans votre code. Par exemple, le "Hello". strPtr est un pointeur au littéral (qui est maintenant compilé dans l'exécutable). Notez qu'il devrait être const char *; vous ne pouvez pas supprimer légalement const selon le standard C et attendez un comportement défini lors de son utilisation. strArray est un tableau contenant une copie du littéral (compilé dans l'exécutable).

Les deux instructions ci-dessus doivent être illégales. le compilateur devrait lancer des erreurs dans les deux cas.

Non, il ne devrait pas. Les deux déclarations sont complètement légales. En raison des circonstances, le premier est indéfini. Ce serait une erreur s'ils étaient des pointeurs vers const char s, cependant. Autant que je sache, les littéraux de chaîne peuvent être définis de la même manière que les autres littéraux et constantes. Cependant, il y a des différences:

// These copy from ROM to RAM at run-time: 
char myString[] = "hello"; 
const int myInt = 42; 
float myFloats[] = { 3.1, 4.1, 5.9 }; 

// These copy a pointer to some data in ROM at run-time: 
const char *myString2 = "hello"; 
const float *myFloats2 = { 3.1, 4.1, 5.9 }; 

char *myString3 = "hello"; // Legal, but... 
myString3[0] = 'j';   // Undefined behavior! (Most likely segfaults.) 

Mon utilisation de ROM et RAM sont ici en général. Si la plate-forme est seulement RAM (par exemple la plupart des programmes Nintendo DS) alors les données de const peuvent être en RAM. Les écritures sont encore indéfinies. L'emplacement des données const ne devrait pas importer pour un programmeur C++ normal.

8
char *strPtr ="Hello" ; 

Définit strPtr un pointeur vers un char pointant vers une chaîne littérale "Hello" - le type efficace de ce pointeur est const char *. Aucune modification autorisée via strPtr à la pointee (invoque UB si vous essayez de le faire). Ceci est une fonctionnalité de compatibilité descendante pour les anciens codes C.Cette convention est obsolète en C++ 0x. Voir l'Annexe C:

Change: Les littéraux de chaîne en const Le type de chaîne est modifié littérale de « tableau de char » à « tableau de const char. » [...]

Justification: Cela évite d'appeler une fonction surchargée inappropriée, qui pourrait être en mesure de modifier son argument.

Effet sur la caractéristique d'origine: Passer à la sémantique d'une entité bien définie. Difficulté de conversion: Transformation syntaxique simple, car les chaînes littérales peuvent être converties en char *; (4.2). Les cas les plus courants sont gérées par un nouveau, mais désapprouvée conversion standard:

char* p = "abc"; // valid in C, deprecated in C++

char* q = expr ? "abc" : "de"; // valid in C, invalid in C++

Comment largement utilisé: Les programmes qui ont une raison légitime pour traiter des chaînes littérales comme des pointeurs à la mémoire potentiellement modifiable sont probablement rares.

char strArray[] ="Hello"; 

Le type déclaré de strPtr est - il est un tableau de caractères de taille non spécifiée contenant la chaîne Hello y compris le terminateur null-à-dire 6 caractères. Cependant, l'initialisation en fait un type complet et son type est un tableau de 6 caractères. La modification via strPtr est correcte.

Où exactement les chaînes littérales sont-elles stockées?

Mise en œuvre définie.

+0

"Le type déclaré de strPtr est", voulez-vous dire strArray? – 4pie0

1

Les anciens C et C++ compilateurs ont été purement basée sur le codage à faible niveau où des normes plus élevées de protection des données ne sont pas disponibles, et ils ne peuvent même être appliquées, généralement en C et C++ vous pouvez écrire tout ce que vous voulez ..

Vous pouvez même écrire un code pour accéder et modifier vos pointeurs const, si vous savez comment jouer avec les adresses.

Bien que C++ impose une protection de niveau de compilation, mais il n'y a aucune protection à l'exécution. Vous pouvez certainement accéder à votre propre pile, et utiliser ses valeurs pour manipuler toutes les données qui viennent dans le pointeur const. C'est la raison pour laquelle C# a été inventé où peu de normes de niveau supérieur sont appliquées parce que tout ce que vous accédez est une référence, c'est une structure fixe régissant toutes les règles de protection de données et un pointeur caché inaccessible et non modifié. La différence majeure est que C++ ne peut vous offrir qu'une protection à la compilation, mais C# vous protégera même lors de l'exécution.

Questions connexes