web-dev-qa-db-fra.com

La conversion du littéral de chaîne en char * est déconseillée

Je reçois toujours l'erreur "La conversion du littéral de chaîne en char * est obsolète" dans mon code. Le but du code est d'utiliser un pointeur vers pointeur pour affecter à string1 et string2 un mot, puis l'imprimer. Comment puis-je réparer cela?

Voici mon code:

#include <iostream>
using namespace std;

struct WORDBLOCK
{
    char* string1;
    char* string2;
};

void f3()
{
    WORDBLOCK Word;

    Word.string1 = "Test1";
    Word.string2 = "Test2";


    char *test1 = Word.string1;
    char *test2 = Word.string2;

    char** teststrings;

    teststrings = &test1;
    *teststrings = test2;

    cout << "The first string is: "
         << teststrings
         << " and your second string is: "
         << *teststrings
         << endl;  
}
26
Andrew T

Les littéraux de chaîne C++ sont des tableaux de constchar, ce qui signifie que vous ne pouvez pas les modifier légalement.

Si vous souhaitez affecter en toute sécurité un littéral de chaîne à un pointeur (ce qui implique une conversion implicite de tableau en pointeur), vous devez déclarer le pointeur cible comme const char*, Pas seulement comme char*.

Voici une version de votre code qui se compile sans avertissements:

#include <iostream>

using namespace std;

struct WORDBLOCK
{
    const char* string1;
    const char* string2;
};

void f3()
{
    WORDBLOCK Word;

    Word.string1 = "Test1";
    Word.string2 = "Test2";

    const char *test1 = Word.string1;
    const char *test2 = Word.string2;

    const char** teststrings;

    teststrings = &test1;
    *teststrings = test2;

    cout << "The first string is: "
         << teststrings
         << " and your second string is: "
         << *teststrings
         << endl;
}

Considérez ce qui pourrait arriver si le langage ne le faisait pas imposait cette restriction:

#include <iostream>
int main() {
    char *ptr = "some literal";  // This is invalid
    *ptr = 'S';
    std::cout << ptr << "\n";
}

Un (non -const) char* Vous permet de modifier les données vers lesquelles pointe le pointeur. Si vous pouviez affecter un littéral de chaîne (converti implicitement en un pointeur vers le premier caractère de la chaîne) à un simple char*, Vous seriez en mesure d'utiliser ce pointeur pour modifier le littéral de chaîne sans avertissements de la compilateur. Le code invalide ci-dessus, si cela a fonctionné, s'imprimerait

Some literal

- et il pourrait en fait le faire sur certains systèmes. Sur mon système, cependant, il meurt avec une erreur de segmentation car il tente d'écrire dans la mémoire en lecture seule (pas la ROM physique, mais la mémoire qui a été marquée comme en lecture seule par le système d'exploitation).

(Un côté: les règles de C pour les littéraux de chaîne sont différentes des règles de C++. En C, un littéral de chaîne est un tableau de char, pas un tableau de const char - - mais tenter de le modifier a un comportement indéfini. Cela signifie qu'en C, vous pouvez légalement écrire char *s = "hello"; s[0] = 'H';, et le compilateur ne se plaindra pas nécessairement - mais le programme est susceptible de mourir avec une erreur de segmentation lorsque vous exécutez Cela a été fait pour maintenir la compatibilité descendante avec le code C écrit avant l'introduction du mot clé const. C++ avait const dès le début, donc ce compromis particulier n'était pas nécessaire.)

44
Keith Thompson