Как избавиться от ‘deprecated conversion from string constant to ' char*’ warnings в GCC?
поэтому я работаю над чрезвычайно большой кодовой базой и недавно обновлен до gcc 4.3, который теперь запускает это предупреждение:
предупреждение: устаревшее преобразование из Строковой константы в’char*'
очевидно, правильный способ исправить это-найти каждое объявление, как
char *s = "constant string";
или вызов функции, как:
void foo(char *s);
foo("constant string");
и сделать их const char
указатели. Однако это означало бы прикосновение к файлам 564, минимум, что не является задачу я хочу выполнить в данный момент. Проблема сейчас в том, что я бегу с -werror
, поэтому мне нужно как-то подавить эти предупреждения. Как я могу это сделать?
23 ответов
любые функции, в которые вы передаете строковые литералы "I am a string literal"
должны использовать char const *
как тип вместо char*
.
если вы собираетесь что-то исправить, исправить это правильно.
объяснение:
вы не можете использовать строковые литералы для инициализации строк, которые будут изменены, потому что они имеют тип const char*
. Отбрасывая константу, чтобы позже изменить их,неопределено поведение, так что вы должны скопировать const char*
строки char
by char
в динамически выделяемой char*
строки, чтобы изменить их.
пример:
#include <iostream>
void print(char* ch);
void print(const char* ch) {
std::cout<<ch;
}
int main() {
print("Hello");
return 0;
}
Проверьте gcc в Диагностический Прагма поддержка, и список - W параметры предупреждения (изменен: новая ссылка на варианты предупреждения).
для GCC, вы можете использовать #pragma warning
директивы, как пояснил здесь.
у меня была похожая проблема, я решил ее так:
#include <string.h>
extern void foo(char* m);
int main() {
// warning: deprecated conversion from string constant to ‘char*’
//foo("Hello");
// no more warning
char msg[] = "Hello";
foo(msg);
}
является ли это подходящим способом решения этой проблемы? У меня нет доступа к foo
адаптировать его к accept const char*
, хотя это было бы лучшим решением (потому что foo
не меняет m
).
Если это активная база кода, Вы все равно можете обновить базу кода. Конечно, выполнение изменений вручную невозможно, но я считаю, что эта проблема может быть решена раз и навсегда одним
Я не могу использовать параметр компилятора. Поэтому я повернул это:
char *setf = tigetstr("setf");
для этого:
char *setf = tigetstr((char *)"setf");
вот как это сделать встроенным в файл, поэтому вам не нужно изменять свой Makefile.
// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"
вы можете позже...
#pragma GCC diagnostic pop
заменить
char *str = "hello";
С
char *str = (char*)"hello";
или если вы вызываете функцию:
foo("hello");
заменить
foo((char*) "hello");
вместо:
void foo(char *s);
foo("constant string");
это работает:
void foo(const char s[]);
foo("constant string");
Test string
является строкой const. Таким образом, вы можете решить так:
char str[] = "Test string";
или:
const char* str = "Test string";
printf(str);
сделайте типизацию из постоянной строки в указатель char, т. е.
char *s = (char *) "constant string";
вы также можете создать записываемую строку из Строковой константы, вызвав strdup()
.
например, этот код генерирует предупреждение:
putenv("DEBUG=1");
однако следующий код этого не делает (он делает копию строки в куче перед ее передачей в putenv
):
putenv(strdup("DEBUG=1"));
в этом случае (и, возможно, в большинстве других) отключение предупреждения-плохая идея-это не просто так. Другой альтернативой (делая все строки записываемыми по умолчанию) является потенциально неэффективно.
слушайте, что компилятор говорит вам!
смотреть на эту ситуацию:
typedef struct tagPyTypeObject
{
PyObject_HEAD;
char *name;
PrintFun print;
AddFun add;
HashFun hash;
} PyTypeObject;
PyTypeObject PyDict_Type=
{
PyObject_HEAD_INIT(&PyType_Type),
"dict",
dict_print,
0,
0
};
смотрите поле имени, в gcc он компилируется без предупреждения, но в g++ это будет, я не знаю почему.
В C++, Заменить:
char *str = "hello";
С:
std::string str ("hello");
и если вы хотите сравнить это:
str.compare("HALLO");
Я не понимаю, как применить ваше решение: (- kalmanIsAGameChanger
работая с Arduino Sketch, у меня была функция, вызывающая мои предупреждения.
исходная функция: char StrContains (char *str, char *sfind)
чтобы остановить предупреждения, я добавил const перед char * str и char * sfind.
изменено: char StrContains (const char *str, const char *sfind).
все предупреждения ушел.
просто используйте опцию-w для g++
пример:
G++ и-З -О простой.o простой.cpp-lpthread
помните, что это не предотвращает устаревание, а предотвращает отображение предупреждающего сообщения на терминале.
теперь, если вы действительно хотите избежать устаревания, используйте ключевое слово const следующим образом:
const char* s="constant string";
почему бы вам не использовать -Wno-deprecated
возможность игнорировать устаревшие предупреждающие сообщения?
ответ BlackShift очень полезен, и я использовал его как:
extern string execute(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[256];
std::string result = " ";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
int main(){
char cmd[]="grep -A1 'xml' out1.txt | grep read|awk -F'=' 'BEGIN{sum=0}{sum=sum+$NF}END{print sum}'";
string result=execute(cmd);
int numOfBytes= atoi(result.c_str());
cout<<"Number of bytes = "<<numOfBytes<<endl;
return 0;
}
проблема сейчас в том, что я бегу с-Werror
Это ваша настоящая проблема, ИМО. Вы можете попробовать несколько автоматических способов перехода от (char *) к (const char*), но я бы поставил на них деньги, а не просто работать. Вы должны иметь человека для хоть какой работы. В краткосрочной перспективе просто игнорируйте предупреждение (но IMO оставьте его включенным, или он никогда не будет исправлен) и просто удалите-Werror.
спасибо всем за помощь. Выбор здесь и там приходит это решение. Это компилирует чистые. Код еще не протестирован. Завтра... возможно...
const char * timeServer[] = { "pool.ntp.org" }; // 0 - Worldwide
#define WHICH_NTP 0 // Which NTP server name to use.
...
sendNTPpacket(const_cast<char*>(timeServer[WHICH_NTP])); // send an NTP packet to a server
...
void sendNTPpacket(char* address) { code }
Я знаю, что в массиве timeServer есть только 1 элемент. Но могло быть и больше. Остальные были прокомментированы, чтобы сохранить память.
PyTypeObject PyDict_Type=
{ ...
PyTypeObject PyDict_Type=
{
PyObject_HEAD_INIT(&PyType_Type),
"dict",
dict_print,
0,
0
};
смотрите поле имени, в gcc он компилируется без предупреждения, но в g++ это будет, я не знаю почему.
на gcc (Compiling C)
,-Wno-write-strings активна по умолчанию.
на g++ (Compiling C++)
-Wwrite-строки активны по умолчанию
вот почему существует другое поведение.
Для нас используются макросы Boost_python
создает такие предупреждения.
Поэтому мы используем -Wno-write-strings
при компиляции C++, так как мы всегда используем -Werror