Как избавиться от `устаревшего преобразования из строковой константы в 'char*'` предупреждений в GCC?
Поэтому я работаю над чрезвычайно большой кодовой базой и недавно обновлена до gcc 4.3, который теперь вызывает это предупреждение:
предупреждение: устаревшее преобразование из строковой константы в 'char*'
Очевидно, что правильный способ исправить это - найти каждое объявление как
char *s = "constant string";
или вызов функции как:
void foo(char *s);
foo("constant string");
и сделать их const char
указатели. Однако это означало бы касание как минимум 564 файлов, что не является задачей, которую я хочу выполнить в данный момент. Проблема сейчас в том, что я бегу с -werror
поэтому мне нужен какой-то способ подавить эти предупреждения. Как я могу это сделать?
23 ответа
Я верю прохождение -Wno-write-strings
GCC подавит это предупреждение.
Любые функции, в которые вы передаете строковые литералы "I am a string literal"
следует использовать char const *
как тип вместо char*
,
Если вы собираетесь что-то исправить, исправьте это правильно.
Объяснение:
Вы не можете использовать строковые литералы для инициализации строк, которые будут изменены, потому что они имеют тип const char*
, Отмена константности для последующего их изменения - неопределенное поведение, поэтому вам нужно скопировать const char*
строки char
от char
в динамически распределяемый char*
строки, чтобы изменить их.
Пример:
#include <iostream>
void print(char* ch);
void print(const char* ch) {
std::cout<<ch;
}
int main() {
print("Hello");
return 0;
}
У меня была похожая проблема, я решил ее так:
#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
адаптировать его, чтобы принять const char*
хотя это было бы лучшим решением (потому что foo
не меняется m
).
Проверьте поддержку gcc Diagnostic Pragma и список параметров -W предупреждений (изменено: новая ссылка на параметры предупреждений).
Для GCC, вы можете использовать #pragma warning
Директивы, как описано здесь.
Если это активная кодовая база, вы все равно можете обновить кодовую базу. Конечно, внесение изменений вручную невозможно, но я считаю, что эту проблему можно решить раз и навсегда одним sed
команда. Я не пробовал, однако, так что возьмите следующее с солью.
find . -exec sed -E -i .backup -n \
-e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;
Это может не найти все места (даже если не учитывать вызовы функций), но это уменьшит проблему и позволит выполнить несколько оставшихся изменений вручную.
Вот как это сделать в файле, так что вам не нужно изменять ваш 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");
Я не могу использовать переключатель компилятора. Итак, я превратил это:
char *setf = tigetstr("setf");
к этому:
char *setf = tigetstr((char *)"setf");
Вместо:
void foo(char *s);
foo("constant string");
Это работает:
void foo(const char s[]);
foo("constant string");
В C++ используйте const_cast
как показано ниже
char* str = const_cast<char*>("Test string");
Test string
константная строка Таким образом, вы можете решить так:
char str[] = "Test string";
или же:
const char* str = "Test string";
printf(str);
Почему бы просто не использовать приведение типов?
(char*) "test"
Делать типизацию от константной строки до указателя на символ, т.е.
char *s = (char *) "constant string";
Вы также можете создать доступную для записи строку из строковой константы, вызвав strdup()
,
Например, этот код генерирует предупреждение:
putenv("DEBUG=1");
Однако следующий код этого не делает (он создает копию строки в куче, прежде чем передать ее putenv
):
putenv(strdup("DEBUG=1"));
В этом случае (и, возможно, в большинстве других) отключение предупреждения является плохой идеей - оно есть по причине. Другая альтернатива (по умолчанию все строки доступны для записи) потенциально неэффективна.
Послушайте, что говорит вам компилятор!
Я не понимаю, как применить ваше решение:(- kalmanIsAGameChanger
Работая с Arduino Sketch, у меня была функция, вызывающая мои предупреждения.
Оригинальная функция: char StrContains (char * str, char * sfind)
Чтобы прекратить предупреждения, я добавил const перед char * str и char * sfind.
Изменено: char StrContains(const char *str, const char *sfind).
Все предупреждения ушли.
Увидеть эту ситуацию:
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");
Спасибо всем за помощь. Выбор здесь и там приходит это решение. Это компилируется чисто. Еще не проверяли код. Может быть, завтра...
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 }
Я знаю, что есть только 1 элемент в массиве timeServer. Но могло быть и больше. Остальные были закомментированы, чтобы сохранить память.
Просто используйте опцию -w для g ++
пример:
g ++ -w -o simple.o simple.cpp -lpthread
Помните, что это не предотвращает устаревание, а предотвращает вывод предупреждающего сообщения на терминал.
Теперь, если вы действительно хотите избежать устаревания, используйте ключевое слово const:
const char* s="constant string";
Ответ 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;
}
Проходя
string constants
функциям напишите это как:
void setpart(const char name[]);
setpart("Hello");
вместо
const char name[]
, вы также можете написать
const char \*name
Мне удалось удалить эту ошибку:
[Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Проблема сейчас в том, что я работаю с -Werror
Это твоя настоящая проблема, ИМО. Вы можете попробовать некоторые автоматизированные способы перехода от (char *) к (const char *), но я бы положил деньги на них, а не просто на работу. Вы должны будете привлекать человека, по крайней мере, для выполнения некоторых работ. В краткосрочной перспективе просто проигнорируйте предупреждение (но IMO оставьте его включенным, иначе оно никогда не будет исправлено) и просто удалите -Werror.
Объявить строку как const
решит проблему:
char const*s = "constant string";
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++)
-Write-Strings активен по умолчанию
Вот почему существует другое поведение. Для нас используются макросы Boost_python
генерирует такие предупреждения. Итак, мы используем -Wno-write-strings
при компиляции C++, так как мы всегда используем -Werror
Почему бы вам не использовать -Wno-deprecated
возможность игнорировать устаревшие предупреждающие сообщения?