Преобразование из String Literal в Char * устарело - программирование
Подтвердить что ты не робот

Преобразование из String Literal в Char * устарело

Я продолжаю получать ошибку "Преобразование из строкового литерала в char * устарело" в моем коде. Целью кода является использование указателя-указателя для назначения string1 и string2 слова, а затем распечатка. Как я могу это исправить?

Вот мой код:

#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;  
}
4b9b3361

Ответ 1

Строковые литералы С++ представляют собой массивы const char, что означает, что вы не можете их законным образом модифицировать.

Если вы хотите безопасно назначить строковый литерал указателю (который подразумевает неявное преобразование между массивами и указателями), вам нужно объявить целевой указатель как const char*, а не только как char*.

Вот версия вашего кода, которая компилируется без предупреждений:

#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;
}

Подумайте, что может случиться, если язык не наложил это ограничение:

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

A (не const) char* позволяет вам изменять данные, на которые указывает указатель. Если вы можете назначить строковый литерал (неявно преобразованный в указатель на первый символ строки) в обычный char*, вы сможете использовать этот указатель для изменения строкового литерала без предупреждения от компилятора. Недопустимый код выше, если он сработает, будет печатать

Some literal

- и это может на самом деле сделать это на некоторых системах. В моей системе, однако, он умирает с ошибкой сегментации, потому что он пытается записать в постоянную память (не физическое ПЗУ, а память, помеченную как операционная система только для чтения).

(В стороне: правила C для строковых литералов отличаются от правил С++. В C строковый литерал представляет собой массив char, а не массив const char - но попытка его изменения имеет undefined Это означает, что в C вы можете юридически написать char *s = "hello"; s[0] = 'H';, и компилятор не обязательно будет жаловаться, но программа, скорее всего, умрет с ошибкой сегментации при ее запуске. Это было сделано для поддержания обратной совместимости с C код, написанный перед ключевым словом const. С++ имел const с самого начала, поэтому этот конкретный компромисс не был необходим.)