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

StackOverflow https://stackoverflow.com/questions/1524356

Вопрос

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

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

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

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

myClass obj("example");

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

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

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

Это было полезно?

Решение

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

char* pointer_to_nonconst = "string literal";

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

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

Другие советы

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

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

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

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

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

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

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

Как ответь нет.2 от fnieto - Фернандо Ньето ясно и правильно описывает, что это предупреждение выдается, потому что где-то в вашем коде вы делаете (а не в опубликованном вами коде) что-то вроде:

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

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

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

То есть просто приведите string постоянный до (char *).

Есть 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");

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

На самом деле строковый константный литерал не является ни const char * и не char*, а char[].Это довольно странно, но это записано в спецификациях C++;Если вы измените его, поведение не будет определено, поскольку компилятор может сохранить его в сегменте кода.

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

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

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

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

foo("Hello")

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

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

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

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

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

Причина этой проблемы (которую еще труднее обнаружить, чем проблему с 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 как указатель на константный символ.Это означает, что данные, на которые указывает этот указатель, постоянны.Указатель можно изменить, но любая попытка изменить данные приведет к ошибке компиляции.
    1. str++ ; : ДЕЙСТВИТЕЛЬНЫЙ.Мы изменяем указатель, а не данные, на которые он указывает.
    2. *str = 'a'; : НЕВЕРНЫЙ.Мы пытаемся изменить данные, на которые указывают.
  2. char* const str :Объявите str как константный указатель на char.Это означает, что точка теперь постоянна, но и указываемые данные тоже нет.Указатель нельзя изменить, но мы можем изменить данные с помощью указателя.
    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 ↔ английского языка для преобразования C декларации превращаются в понятные утверждения на английском языке и наоборот.Это C единственный инструмент и, следовательно, не будет поддерживать вещи (например, constexpr), которые являются эксклюзивными для C++.

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

#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';
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top