La norme C ++ 11 (ISO / IEC 14882: 2011) dit dans § C.1.1
:
char* p = "abc"; // valid in C, invalid in C++
Pour le C ++, c'est OK car un pointeur vers un littéral de chaîne est dangereux car toute tentative de le modifier conduit à un crash. Mais pourquoi est-ce valable en C?
Le C ++ 11 dit aussi:
char* p = (char*)"abc"; // OK: cast added
Ce qui signifie que si un cast est ajouté à la première instruction, il devient valide.
Pourquoi le cast rend-il la deuxième instruction valide en C ++ et en quoi est-elle différente de la première? N'est-ce pas encore nocif? Si c'est le cas, pourquoi la norme dit-elle que c'est OK?
char[]
en premier lieu. Le second est unconst_cast
déguisé.OK
.const
, donc ils ne l'étaient pas nécessairementconst
.Réponses:
Jusqu'à C ++ 03, votre premier exemple était valide, mais utilisait une conversion implicite obsolète - un littéral de chaîne devrait être traité comme étant de type
char const *
, car vous ne pouvez pas modifier son contenu (sans provoquer un comportement indéfini).Depuis C ++ 11, la conversion implicite qui était obsolète a été officiellement supprimée, donc le code qui en dépend (comme votre premier exemple) ne devrait plus être compilé.
Vous avez noté une façon d'autoriser la compilation du code: bien que la conversion implicite ait été supprimée, une conversion explicite fonctionne toujours, vous pouvez donc ajouter un cast. Je ne cependant considérer cette « fixation » le code.
Pour vraiment corriger le code, il faut changer le type du pointeur pour le type correct:
Quant à savoir pourquoi il était autorisé en C ++ (et l'est toujours en C): simplement parce qu'il y a beaucoup de code existant qui dépend de cette conversion implicite, et casser ce code (au moins sans avertissement officiel) a apparemment semblé aux comités standard comme Une mauvaise idée.
la source
char const *p = "abc";
est « valable et sûre dans les deux C et C ++ », pas « valide et en sécurité dans soit C ou C ++ ».Il est valide en C pour des raisons historiques. C spécifiait traditionnellement que le type d'un littéral de chaîne était
char *
plutôt queconst char *
, bien qu'il le qualifie en disant que vous n'êtes pas réellement autorisé à le modifier.Lorsque vous utilisez un cast, vous dites essentiellement au compilateur que vous connaissez mieux que les règles de correspondance de type par défaut, et cela rend l'affectation OK.
la source
char[N]
et a été changé enconst char[N]
. Des informations de taille y sont attachées.char[N]
mais paschar*
par exemple"abc"
estchar[4]
Vous pouvez également utiliser strdup :
la source