2010-09-03 5 views

Répondre

7

La norme exige que les chaînes littérales soient définies const. Vous ne pouvez pas le changer.

Le compilateur place le littéral dans une section de mémoire en lecture seule. Vous pouvez sortir l'assemblage et observer ceci. Si vous utilisez GCC, cela se fait via l'option -s. Il placera la chaîne dans une section .rodata.

+0

et si j'écris char arr [10] = "nyks"; arr [2] = 'p'; montrera-t-il une erreur de seg? – Kraken

+1

@hopeful, non. C'est bien, puisque vous allouez un tableau (modifiable) sur la pile. Comme je l'ai noté ci-dessus, vous pouvez omettre la taille afin que C le calcule. –

+1

Non, en C, les littéraux de chaînes n'ont pas de type 'const'. Cependant, il est un comportement indéfini pour leur écrire. –

15

Il est un comportement non défini pour essayer d'écraser un littéral de chaîne. C99 §6.4.5/6:

Si le programme tente de modifier cette un tableau, le comportement est fi nie unde.

Ceci est mis à jour dans l'Annexe J.2 (comportement indéfini).

Si vous faites place:

char p[] = "nyks"; 

vous pouvez allouer et initialiser un tableau automatique de caractères (pile). Dans ce cas, il est parfaitement possible de modifier les éléments.

+0

+ il n'est plus permis d'avoir des déclarations littérales de chaînes non-constantes. GCC émettra un grand avertissement rouge. –

+0

+1 pour référence à la spécification – linuxuser27

0

littérales cordes ne sont pas modifiables ... La capacité d'écrire char *p="nyks"; est en fait un trou de système de type en C.

+0

Comment est-ce un trou de système de type? – alternative

+0

Pour des raisons historiques, le compilateur a été autorisé à rejeter silencieusement 'const' dans ce cas. Bien sûr, au moment où 'const' a été inventé et ils ont remarqué qu'une constante de chaîne doit effectivement être' const char * ', il a probablement été jugé trop gros pour interdire l'affectation à' char * '. – RBerteig

+0

@mathepic C'est du point de vue C++, au moins. En C++, un littéral de caractère est de type const char [N]. Un littéral de chaîne peut être implicitement converti en char non-const * (qualification const supprimée sans cast). C'est un trou de système de type en C++, mais ce comportement a été hérité de C. C'est une fonctionnalité déconseillée en C++, et sera entièrement supprimée en C++ 0x. Voici ce que le standard C a à dire sur cette question: "Si le programme tente de modifier un tel tableau, le comportement n'est pas défini." où 'un tel tableau' est un tableau de caractères qui contient une chaîne littérale. – usta

1

Cela se traduit (essentiellement):

#include<stdio.h> 
const char privatestring[5] = {"nyks"}; 

void main() 
{ 
    char *p = const_cast<char*>(privatestring); 
    p[2]='n';   

    printf("%s",p);   
}   

Le compilateur est autorisé à mettre privatestring quelque part où vous avez seulement un accès en lecture. Il fait la const_cast pour la rétrocompatibilité avec les programmes écrits avant qu'il ne s'agisse d'un mot clé const.

3

D'autres réponses disent la vue du point de vue des normes, mais voici pourquoi il se bloque.

Les compilateurs placent généralement les littéraux de programme - en particulier les chaînes - dans la mémoire morte. La mémoire est marquée en lecture seule par le système d'exploitation, de sorte que toute tentative d'écriture sera piégée et, sur votre plate-forme, c'est ce que l'erreur de segmentation indique; une tentative d'effectuer une opération sur une mémoire non autorisée. L'autre type de crash associé à une mauvaise utilisation de la mémoire est une erreur de bus, qui indique généralement un accès mémoire non aligné ou une écriture sur une page qui n'est pas mappée du tout. Pour le code C, la différence est presque entièrement académique (d'autres implémentations de langage utilisent ces fautes pour les aider à gérer la mémoire).

Notez que le piégeage des écritures en lecture seule est indépendant de la sémantique officielle de la langue. Bien que vous ayez un char* pointant dessus, vous ne pouvez toujours pas l'écrire. Traitez toujours les littéraux de programme comme s'ils pointent vers une mémoire constante et vous ne vous tromperez pas (ils ne le sont pas par défaut en raison de la nécessité de prendre en charge la compatibilité avec les anciens programmes).

+0

Et la norme (C89) ne spécifie pas ce qui se passe lorsque vous écrivez dans un littéral précisément parce qu'ils ne veulent pas spécifier la manière exacte dont un crash se produit, et parce qu'ils veulent aussi permettre aux compilateurs de supporter les chaînes inscriptibles si ils voulaient (par exemple, via un switch, gcc a '' fingerable-strings' pour faire ce genre de chose, mais en ayant besoin c'est juste une indication d'un programme gravement brisé si vous me demandez). –

1

La valeur est un littéral de chaîne qui ne peut pas être modifié car les littéraux sont stockés dans la mémoire morte, essayez plutôt p []. Les erreurs de segmentation se produisent généralement en raison d'une mauvaise utilisation des pointeurs.

Questions connexes