162 votes

Conversion dépréciée en C++ d'une constante de chaîne en 'char*'.

J'ai une classe avec un private char str[256];

et pour cela j'ai un constructeur explicite :

explicit myClass(const char *func)
{
    strcpy(str,func);
}

Je l'appelle ainsi :

myClass obj("example");

Lorsque je compile le tout, j'obtiens l'avertissement suivant :

Conversion dépréciée d'une constante de chaîne en 'char*'.

Pourquoi cela se produit-il ?

2 votes

Vous devez utiliser strncpy(str, func, 255) au lieu de strcpy(str, func) pour une copie plus sûre. Et n'oubliez pas d'ajouter le ' \0 à la fin de la chaîne puisque strncpy ne l'ajoute pas.

3 votes

Il est encore plus sûr de dire "strncpy(str, func, sizeof(str)) ; str[sizeof(str) - 1] = '". \0 ' ;"

3 votes

Je ne pense pas que le code ci-dessus donne l'avertissement que vous avez cité, bien que je sois sûr qu'un code assez similaire le ferait. Afin d'obtenir des réponses significatives, vous devriez poster un exemple minimal et compilant qui produit l'avertissement.

159voto

sellibitze Points 13607

Il s'agit d'un message d'erreur que vous voyez chaque fois que vous vous trouvez dans une situation comme la suivante :

char* pointer_to_nonconst = "string literal";

Pourquoi ? Eh bien, le C et le C++ diffèrent dans le type de la chaîne littérale. En C, le type est array of char et en C++, il est constant tableau de caractères. Dans tous les cas, vous n'êtes pas autorisé à modifier les caractères de la chaîne littérale, donc le const en C++ n'est pas vraiment une restriction mais plutôt une sécurité de type. Une conversion de const char* a char* n'est généralement pas possible sans un moulage explicite pour des raisons de sécurité. Cependant, pour des raisons de compatibilité ascendante avec le C, le langage C++ permet toujours d'assigner un littéral de chaîne de caractères à un objet de type char* et vous donne un avertissement sur le fait que cette conversion est obsolète.

Donc, quelque part, il vous manque un ou plusieurs const dans votre programme pour vérifier l'exactitude des constantes. Mais le code que vous nous avez montré n'est pas le problème car il ne fait pas ce genre de conversion dépréciée. L'avertissement doit provenir d'un autre endroit.

23 votes

Il est regrettable, compte tenu des avis et des votes sur cette question, que le PO n'ait jamais fourni de code démontrant réellement le problème.

2 votes

Vous pouvez reproduire le problème avec le code de l'OP en supprimant l'option const de la MyClass ...alors vous pouvez le corriger en ajoutant l'option const arrière.

148voto

L'avertissement :

Conversion dépréciée d'une constante de chaîne en 'char*'.

est donné parce que vous faites quelque part (pas dans le code que vous avez posté) quelque chose comme :

void foo(char* str);
foo("hello");

Le problème est que vous essayez de convertir une chaîne de caractères littérale (de type const char[] ) à char* .

Vous pouvez convertir un const char[] a const char* parce que le tableau se désintègre dans le pointeur, mais ce que vous faites, c'est faire d'un mutable une constante.

Cette conversion est probablement autorisée pour la compatibilité C et vous donne juste l'avertissement mentionné.

104voto

sactiw Points 7717

Comme Répondez non. 2 par fnieto - Fernando Nieto décrit clairement et correctement que cet avertissement est donné parce que quelque part dans votre code vous faites (pas dans le code que vous avez posté) quelque chose comme :

void foo(char* str);
foo("hello");

Toutefois, si vous souhaitez que votre code ne comporte pas d'avertissement, il vous suffit d'effectuer les modifications correspondantes dans votre code :

void foo(char* str);
foo((char *)"hello");

C'est-à-dire qu'il suffit de lancer le string constant à (char *) .

19 votes

Vous pouvez aussi créer la fonction : void foo(const char* str)

4 votes

@Caprooja Oui, déclarer le paramètre comme 'pointeur vers une constante' fonctionnera également dans ce cas. Mais avec ce changement, l'utilisateur ne peut plus modifier/réaffecter la valeur stockée à l'adresse utilisant le pointeur 'str', ce qu'il pourrait faire dans la partie implémentation. Il s'agit donc d'un élément auquel vous devez prêter attention.

1 votes

@sactiw Y a-t-il des raisons de garder void foo(char* str) tel quel ? Je croyais qu'on ne pouvait pas moduler str en foo de toute façon, même le paramètre est écrit comme non-const.

43voto

anil Points 63

Il existe 3 solutions :

Solution 1 :

const char *x = "foo bar";

Solution 2 :

char *x = (char *)"foo bar";

Solution 3 :

char* x = (char*) malloc(strlen("foo bar")+1); // +1 for the terminator
strcpy(x,"foo bar");

Les tableaux peuvent également être utilisés à la place des pointeurs car un tableau est déjà un pointeur constant.

8 votes

Pour la solution 3, il y a strdup . Contrairement à votre code, il allouera de l'espace pour le caractère NUL de fin, et ne dépassera pas l'allocation.

2 votes

La solution 2 est à éviter.

1 votes

En fait, la solution 2 peut être : char *x = static_cast<char*>("foo bar") en C++.

4voto

dan ionescu Points 74

En fait, un littéral constant de chaîne n'est ni un const char * ni un char* mais un char[]. C'est assez étrange mais c'est écrit dans les spécifications c++ ; Si vous le modifiez le comportement est indéfini car le compilateur peut le stocker dans le segment de code.

5 votes

Je dirais qu'il s'agit de const char[] car en tant que rvalue vous ne pouvez pas le modifier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X