У меня есть класс с private char str[256];
и для этого у меня есть явный конструктор:
explicit myClass(const char *func)
{
strcpy(str,func);
}
Я называю это так:
myClass obj("example");
Когда я компилирую это, я получаю следующее предупреждение:
устаревшее преобразование из строковой константы в 'char *'
Почему это происходит?
c++
string
explicit-constructor
mkamthan
источник
источник
strncpy(str, func, 255)
вместоstrcpy(str, func)
более безопасной копии. И затем не забудьте добавить '\ 0' в конце строки, так как strncpy не добавляет его.Ответы:
Это сообщение об ошибке вы видите всякий раз, когда у вас возникает такая ситуация:
Зачем? Ну, C и C ++ различаются по типу строкового литерала. В C тип является массивом char, а в C ++ - постоянным массивом char. В любом случае вам не разрешено изменять символы строкового литерала, поэтому const в C ++ на самом деле не ограничение, а скорее вопрос безопасности типов. Преобразование из
const char*
вchar*
обычно невозможно без явного приведения по соображениям безопасности. Но для обратной совместимости с C язык C ++ все еще позволяет присваивать строковый литерал achar*
и выдает предупреждение о том, что это преобразование не рекомендуется.Таким образом, где-то вам не хватает одного или нескольких
const
символов в вашей программе для правильности констант. Но код, который вы показали нам, не является проблемой, так как он не делает такого рода устаревшее преобразование. Предупреждение, должно быть, пришло из другого места.источник
const
изMyClass
конструктора ... затем вы можете исправить ее, добавивconst
обратно.Предупреждение:
дается, потому что вы делаете где-то (не в коде, который вы опубликовали) что-то вроде:
Проблема в том, что вы пытаетесь преобразовать строковый литерал (с типом
const char[]
) вchar*
.Вы можете преобразовать
const char[]
в,const char*
потому что массив распадается на указатель, но то, что вы делаете, делает изменяемый константу.Это преобразование, вероятно, разрешено для совместимости с C и дает вам упомянутое предупреждение.
источник
Как ответа нет. 2 by fnieto - Фернандо Ньето ясно и правильно описывает, что это предупреждение выдается, потому что где-то в вашем коде вы делаете (не в коде, который вы опубликовали) что-то вроде:
Однако, если вы хотите, чтобы ваш код также не содержал предупреждений, просто внесите соответствующие изменения в свой код:
То есть просто приведите
string
константу к(char *)
.источник
void foo(char* str)
как есть? Я думал, что мы не можем модифицироватьstr
вfoo
любом случае, даже параметр записан как неконстантный.Есть 3 решения:
Решение 1:
Решение 2:
Решение 3:
Массивы также можно использовать вместо указателей, поскольку массив уже является постоянным указателем.
источник
strdup
. В отличие от вашего кода, он будет выделять место для завершающего символа NUL и не будет превышать выделение.Фактически строковая константа-литерал не является ни const char *, ни char *, а char []. Это довольно странно, но записано в спецификациях c ++; Если вы измените его, поведение не определено, потому что компилятор может сохранить его в сегменте кода.
источник
Может быть, вы можете попробовать это:
Меня устраивает
источник
Я решаю эту проблему, добавив этот макрос в начале кода, где-то. Или добавь это
<iostream>
, хе-хе.источник
C_TEXT
подходит для вызова функции (foo(C_TEXT("foo"));
), но требует неопределенного поведения, если значение хранится в такой переменной, какchar *x = C_TEXT("foo");
- любое использованиеx
(кроме присваивания) является неопределенным поведением, поскольку память, на которую он указывает, была освобождена.Причиной этой проблемы (которую еще сложнее обнаружить, чем проблему,
char* str = "some string"
которую объяснили другие) является то, что вы используетеconstexpr
.Кажется, что он будет вести себя подобно
const char* str
, и поэтому не будет вызывать предупреждение, как это происходит раньшеchar*
, но вместо этого он ведет себя какchar* const str
.подробности
Указатель константы и указатель на константу. Разницу между
const char* str
иchar* const str
можно объяснить следующим образом.const char* str
: Объявить str указателем на const char. Это означает, что данные, на которые этот указатель указывает на него, постоянны. Указатель можно изменить, но любая попытка изменить данные приведет к ошибке компиляции.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 gibberish ↔ английский конвертер для преобразования
C
объявлений в легко понятные английские выражения, и наоборот. ЭтоC
единственный инструмент, и поэтому он не будет поддерживать вещи (например, constexpr), которые являются эксклюзивными дляC++
.источник
У меня тоже такая же проблема. Я просто добавил const char * вместо char *. И проблема решена. Как уже упоминалось выше, это совместимая ошибка. C рассматривает строки как массивы символов, а C ++ обрабатывает их как массивы const.
источник
Я считаю, что этот простой класс-обертка полезен для преобразования строк C ++ в
char *
:источник
Следующее иллюстрирует решение, назначьте вашу строку указателю переменной на постоянный массив символов char (строка является постоянным указателем на постоянный массив символов char + plus length):
источник