C++ устарело преобразование строковой константы в 'char*'
-
19-09-2019 - |
Вопрос
У меня есть класс с 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*
и выдает предупреждение о том, что это преобразование устарело.
Итак, где-то вам не хватает одного или нескольких const
s в вашей программе для обеспечения корректности констант.Но код, который вы нам показали, не является проблемой, поскольку он не выполняет такого рода устаревшие преобразования.Предупреждение, должно быть, пришло из какого-то другого места.
Другие советы
Предупреждение:
устаревшее преобразование строковой константы в '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
можно объяснить следующим образом.
const char* str
:Объявите str как указатель на константный символ.Это означает, что данные, на которые указывает этот указатель, постоянны.Указатель можно изменить, но любая попытка изменить данные приведет к ошибке компиляции.str++ ;
: ДЕЙСТВИТЕЛЬНЫЙ.Мы изменяем указатель, а не данные, на которые он указывает.*str = 'a';
: НЕВЕРНЫЙ.Мы пытаемся изменить данные, на которые указывают.
char* const str
:Объявите str как константный указатель на char.Это означает, что точка теперь постоянна, но и указываемые данные тоже нет.Указатель нельзя изменить, но мы можем изменить данные с помощью указателя.str++ ;
: НЕВЕРНЫЙ.Мы пытаемся изменить переменную-указатель, которая является константой.*str = 'a';
: ДЕЙСТВИТЕЛЬНЫЙ.Мы пытаемся изменить данные, на которые указывают.В нашем случае это не приведет к ошибке компиляции, но вызовет ошибка выполнения, так как строка, скорее всего, попадет в раздел скомпилированного двоичного файла, доступный только для чтения.Это утверждение имело бы смысл, если бы у нас была динамически выделяемая память, например.char* const str = new char[5];
.
const char* const str
:Объявите str как константный указатель на константный символ.В этом случае мы не можем изменить ни указатель, ни данные, на которые он указывает.str++ ;
: НЕВЕРНЫЙ.Мы пытаемся изменить переменную-указатель, которая является константой.*str = 'a';
: НЕВЕРНЫЙ.Мы пытаемся изменить данные, на которые указывает этот указатель, который также является постоянным.
В моем случае проблема заключалась в том, что я ожидал constexpr char* str
вести себя как const char* str
, и не char* const str
, так как визуально кажется ближе к первому.
Кроме того, предупреждение, созданное для constexpr char* str = "some string"
немного отличается от char* str = "some string"
.
- Предупреждение компилятора о
constexpr char* str = "some string"
:ISO C++11 does not allow conversion from string literal to 'char *const'
- Предупреждение компилятора о
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';
}