web-dev-qa-db-fra.com

Pourquoi la conversion de chaîne constante en 'char *' est-elle valide en C mais non valide en C ++?

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++, tout va bien, car un pointeur sur un littéral de chaîne est préjudiciable, car toute tentative de le modifier entraîne un blocage. 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 casting est ajouté à la première déclaration, il devient valide.

Pourquoi le casting rend-il la deuxième déclaration valide en C++ et en quoi est-il différent du premier? N'est-ce pas encore nuisible? Si c'est le cas, pourquoi la norme a-t-elle déclaré que tout allait bien?

129
rullof

Jusqu'en C++ 03, votre premier exemple était valide, mais utilisait une conversion implicite déconseillée - un littéral de chaîne devait être traité comme étant de type char const *, car vous ne pouvez pas modifier son contenu (sans provoquer de comportement indéfini ).

À partir de C++ 11, la conversion implicite obsolète a été officiellement supprimée. Par conséquent, le code qui en dépend (comme votre premier exemple) ne devrait plus être compilé.

Vous avez noté un moyen d'autoriser la compilation du code: bien que la conversion implicite ait été supprimée, une conversion explicite fonctionne toujours, vous pouvez donc ajouter une distribution. Je voudrais pas, cependant, considérons que cela "corrige" le code.

Pour véritablement corriger le code, il faut changer le type du pointeur et lui attribuer le type correct:

char const *p = "abc"; // valid and safe in either C or C++.

Pour ce qui est de savoir pourquoi cela a été autorisé en C++ (et l'est toujours): tout simplement parce qu'il y a beaucoup de code existant qui dépend de cette conversion implicite, et le déchiffrer (au moins sans avertissement officiel) semblait apparemment aux comités standard: Une mauvaise idée.

150
Jerry Coffin

C'est valable en C pour des raisons historiques. C spécifiait traditionnellement que le type d'un littéral de chaîne était char * plutôt que const char *, bien qu'il le qualifie en disant que vous n'êtes pas autorisé à le modifier.

Lorsque vous utilisez un transtypage, vous dites essentiellement au compilateur que vous en savez plus que les règles de correspondance de types par défaut, et l'assignation est validée.

10
Barmar