Question

Ce code se comporte bizarre dans MS Visual Studio:

char *s = "hello";
s[0] = 'a';
printf(s); 

Dans la version construire avec l'optimisation est activée, il ne tient pas compte de [0] « a » = et affiche « bonjour ». Sans l'optimisation ou version debug, il se bloque avec violation d'accès.
Est-ce comportement est c ++ conforme à la norme ou non? À mon avis, le compilateur ne devrait permettre des références constantes à littéraux de chaîne, i.e..

const char *s = "hello";

EDIT :. Je sais pourquoi cela fonctionne comme ça, je ne comprends pas pourquoi je suis autorisé à faire référence non const à mémoire morte

Était-ce utile?

La solution

La raison pour laquelle ce code est permis en premier lieu (plutôt que d'exiger la déclaration à être de type char const*) est rétrocompatibilité à l'ancien code C.

La plupart des compilateurs modernes en mode strict émettra un avertissement pour le code ci-dessus, bien!

Autres conseils

Non, ce n'est pas un bogue dans le compilateur. Lorsque vous écrivez:

char* s = "hello";

La "hello" constante de chaîne sera placée dans une section de lecture seule et devrait générer une exception si vous essayez de la modifier. (À l'exception du système d'exploitation, pas une exception C ++).

Pour le rendre accessible en écriture, vous devez soit utiliser un tableau:

char s[] = { 'h', 'e', 'l', 'l', 'o', 0 };

ou, si vous avez vraiment besoin d'un pointeur, faire pointer vers un tableau:

char _s[] = { 'h', 'e', 'l', 'l', 'o', 0 };
char* s = _s;

Je peux voir votre point au sujet des pointeurs ne permettant const à initialisés avec des chaînes littérales, mais je pense que ce serait briser une beaucoup de code existant.

Je pense que les compilateurs C de sont autorisés à allouer littéraux de chaîne en lecture seule pages de mémoire par la norme.

Cela ne fonctionnera pas parce que * s pointe vers l'adresse mémoire d'une constante chaîne, que vous n'êtes pas autorisé à changer.

Je suis en fait un peu surpris que vous ne ne recevez pas une violation d'accès quand il est compilé avec des optimisations.

char *s = "foo";

est un poney délicat. Il ne vous dit pas que cela est vraiment une chaîne de lecture seule, alors qu'en réalité il est. Il en est ainsi, parce que, vous pourriez avoir votre collègue écrire une autre chaîne comme:

char *t = "foo";

Maintenant, le compilateur, à son utile Google gardera un seul exemplaire, et changer un marqueraient un beaucoup du travail que pour vous et votre ami heureux. , Il n'essayez donc de ne pas le faire. Ceci est quelque chose que vous devriez trouver dans la norme. Devinez quoi, ce que vous faites UB invoque.

Cela dit, si vous deviez avoir votre chemin, il briser beaucoup de code existant que les pauvres gars au Comité des normes ne pouvaient pas se permettre. Donc, vous êtes là.

Rappelez-vous le const nous sommes coupables d'utilisation insouciante n'est pas né en un jour. Bjarne a fait beaucoup d'introspection et ainsi fait beaucoup d'autres que de le mettre ou non. En fait, il a eu cette excellente idée d'avoir en lecture seule et écriture seules variables ... mais je vais sauver cette histoire pour un autre jour.

Et enfin, il est notre bon ami C, qui nous devons prendre soin. Alors ...

Comme les autres ont dit, vous ne pouvez pas modifier une chaîne littérale. Je me demande aussi pourquoi vous ne recevez pas un avertissement du compilateur dans votre code. La boîte de compilateur pour comprendre que vous vous essayez d'écrire à mémoire morte.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top