С++ устарело преобразование из строковой константы в 'char *'

У меня есть класс с private char str[256];

и для него у меня есть явный конструктор:

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

Я называю это как:

myClass obj("example");

Когда я скомпилирую это, я получаю следующее предупреждение:

устаревшее преобразование из строковой константы в 'char *'

Почему это происходит?

Ответ 1

Это сообщение об ошибке, которое вы видите всякий раз, когда у вас возникает такая ситуация:

char* pointer_to_nonconst = "string literal";

Зачем? Ну, C и C++ различаются по типу строкового литерала. В C тип является массивом char, а в C++ это постоянный массив char. В любом случае, вам не разрешено изменять символы строкового литерала, поэтому const в C++ на самом деле не ограничение, а скорее вопрос безопасности типов. Преобразование из const char* в char* обычно невозможно без явного приведения по соображениям безопасности. Но для обратной совместимости с C язык C++ по-прежнему позволяет присваивать строковый литерал char* и выдает предупреждение о том, что это преобразование не рекомендуется.

Итак, где-то вам не хватает одного или нескольких const в вашей программе для правильности const. Но код, который вы показали нам, не является проблемой, так как он не делает такого рода устаревшее преобразование. Предупреждение, должно быть, пришло из другого места.

Ответ 2

Предупреждение:

устаревшее преобразование из строковой константы в 'char *'

дается потому, что вы что-то делаете (не в коде, который вы опубликовали), например:

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

Проблема заключается в том, что вы пытаетесь преобразовать строковый литерал (с типом const char[]) в char*.

Вы можете преобразовать const char[] в const char*, потому что массив распадается на указатель, но то, что вы делаете, делает переменную константу.

Это преобразование, вероятно, разрешено для совместимости с C и просто дает вам упомянутое предупреждение.

Ответ 3

Как ответить нет. 2 by fnieto - Fernando Nieto ясно и правильно описывает, что это предупреждение дается, потому что где-то в коде, который вы делаете (не в коде, который вы отправили), что-то вроде:

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

Однако, если вы хотите сохранить код без предупреждения, а затем просто внесите соответствующие изменения в свой код:

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

То есть просто добавьте константу string в (char *).

Ответ 4

Существует 3 решения:

Решение 1:

const char *x = "foo bar";

Решение 2:

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

Решение 3:

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

Массивы также могут использоваться вместо указателей, потому что массив уже является указателем константы.

Ответ 5

Фактически строковый константный литерал не является ни константой char *, ни char *, а char []. Это довольно странно, но записано в спецификациях С++; Если вы его изменяете, поведение undefined, потому что компилятор может сохранить его в сегменте кода.

Ответ 6

Я решаю эту проблему, добавляя этот макрос в начале кода где-то. Или добавьте его в <iostream>, хе-хе.

 #define C_TEXT( text ) ((char*)std::string( text ).c_str())

Ответ 7

Может быть, вы можете попробовать это:

void foo(const char* str) 
{
    // Do something
}

foo("Hello")

Меня устраивает

Ответ 8

У меня тоже такая же проблема. И то, что я просто сделал, просто добавляет const char * вместо char *. И проблема решена. Как упоминалось выше, это совместимая ошибка. C обрабатывает строки как char массивы, тогда как С++ рассматривает их как const char массивы.

Ответ 9

Я считаю, что этот простой класс-обертка полезен для преобразования строк C++ в char *:

class StringWrapper {
    std::vector<char> vec;
public:
    StringWrapper(const std::string &str) : vec(str.begin(), str.end()) {
    }

    char *getChars() {
        return &vec[0];
    }
};

Ответ 10

Худшая часть этого - типичная неоднозначность в злоупотреблении зарезервированным словом "строка", из-за чего можно ошибочно полагать, что "пример".c_str() решит проблему.

Ответ 11

Причиной этой проблемы (которую еще сложнее обнаружить, чем проблему с char* str = "some string" - которую объяснили другие) является то, что вы используете constexpr.

constexpr char* str = "some string";

Кажется, что он будет вести себя подобно const char* str, и поэтому не будет вызывать предупреждение, как это было до char*, но вместо этого он ведет себя как char* const str.

Подробнее

Указатель константы и указатель на константу. Разницу между const char* str и char* const str можно объяснить следующим образом.

  1. const char* str: объявлять str как указатель на const char. Это означает, что данные, на которые этот указатель указывает на него, постоянны. Указатель можно изменить, но любая попытка изменить данные приведет к ошибке компиляции.
    1. str++ ;: ДЕЙСТВИТЕЛЬНО. Мы модифицируем указатель, а не данные, на которые указывают.
    2. *str = 'a';: НЕВЕРНО. Мы пытаемся изменить данные, на которые указывают.
  2. char* const str: объявить str как постоянный указатель на символ. Это означает, что точка теперь постоянна, но данные, на которые указывают, тоже нет. Указатель нельзя изменить, но мы можем изменить данные, используя указатель.
    1. str++ ;: НЕВЕРНО. Мы пытаемся изменить указатель переменной, которая является константой.
    2. *str = 'a';: ДЕЙСТВИТЕЛЬНО. Мы пытаемся изменить данные, на которые указывают. В нашем случае это не приведет к ошибке компиляции, но вызовет ошибку времени выполнения, поскольку строка, скорее всего, попадет в секцию только для чтения скомпилированного двоичного файла. Это утверждение имело бы смысл, если бы у нас была динамически распределенная память, например. char* const str = new char[5];.
  3. const char* const str: объявлять str константным указателем на константный символ. В этом случае мы не можем ни изменить указатель, ни данные, на которые он указывает.
    1. str++ ;: НЕВЕРНО. Мы пытаемся изменить указатель переменной, которая является константой.
    2. *str = 'a';: НЕВЕРНО. Мы пытаемся изменить данные, указанные этим указателем, который также является постоянным.

В моем случае проблема заключалась в том, что я ожидал, что constexpr char* str будет вести себя как const char* str, а не char* const str, поскольку визуально он кажется ближе к первому.

Кроме того, предупреждение, сгенерированное для constexpr char* str = "some string", немного отличается от char* str = "some string".

  1. Предупреждение компилятора для constexpr char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *const'
  2. Предупреждение компилятора для char* str = "some string": ISO C++11 does not allow conversion from string literal to 'char *'.

Совет

Вы можете использовать конвертер C gibberish ↔ English, чтобы преобразовать объявления C в легко понятные английские выражения, и наоборот. Это только инструмент C, и поэтому он не будет поддерживать вещи (например, constexpr), которые являются эксклюзивными для C++.

Ответ 12

Ниже показано решение, присваивается вашей строке указателю переменной постоянному массиву из char (строка является константным указателем на постоянный массив char - плюс длина информации):

#include <iostream>

void Swap(const char * & left, const char * & right) {
    const char *const temp = left;
    left = right;
    right = temp;
}

int main() {
    const char * x = "Hello"; // These works because you are making a variable
    const char * y = "World"; // pointer to a constant string
    std::cout << "x = " << x << ", y = " << y << '\n';
    Swap(x, y);
    std::cout << "x = " << x << ", y = " << y << '\n';
}