Как избавиться от предупреждений `устаревшее преобразование из строковой константы в ‘символ *’ в GCC?
Вопрос
Итак, я работаю над чрезвычайно большой кодовой базой и недавно обновлен до gcc 4.3, который теперь запускает это предупреждение:
предупреждение:устаревшее преобразование строковой константы в ‘char*’
Очевидно, что правильный способ исправить это - найти каждое объявление, подобное
char *s = "constant string";
или вызов функции типа:
void foo(char *s);
foo("constant string");
и сделать их const char
указатели.Однако это означало бы коснуться минимум 564 файлов, что не является задачей, которую я хотел бы выполнять на данный момент.Проблема прямо сейчас в том, что я бегу с -werror
, поэтому мне нужен какой-то способ подавить эти предупреждения.Как я могу это сделать?
Решение
Я верю, что проходящий -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;
}
Ознакомьтесь с 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
адаптировать его, чтобы принять const char*
, хотя это было бы лучшим решением (потому что foo
не меняется m
).
Если это активная кодовая база, вы все равно можете захотеть обновить кодовую базу.Конечно, выполнение изменений вручную невозможно, но я считаю, что эта проблема может быть решена раз и навсегда одним единственным способом sed
команда.Однако я этого не пробовал, так что отнеситесь к нижеследующему с долей скептицизма.
find . -exec sed -E -i .backup -n \
-e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;
Это может привести к обнаружению не всех мест (даже без учета вызовов функций), но это облегчит проблему и позволит выполнить несколько оставшихся изменений вручную.
Я не могу использовать переключатель компилятора.Итак, я превратил это:
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");
В 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";
В C++ Замените:
char *str = "hello";
с:
std::string str ("hello");
И если вы хотите сравнить это:
str.compare("HALLO");
Я не понимаю, как применить ваше решение :( – kalmanIsAGameChanger
Работая с Arduino Sketch, у меня была функция, вызывающая мои предупреждения.
Исходная функция:char StrContains(char *str, char *sfind)
Чтобы остановить предупреждения, я добавил постоянный перед символом *str и символом *sfind.
Измененный:содержит символ 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
};
следите за полем name, в gcc оно компилируется без предупреждения, но в g ++ это произойдет, я не знаю почему.
Вы также можете создать строку, доступную для записи, из строковой константы, вызвав strdup()
.
Например, этот код генерирует предупреждение:
putenv("DEBUG=1");
Однако следующий код этого не делает (он создает копию строки в куче перед передачей ее в putenv
):
putenv(strdup("DEBUG=1"));
В этом случае (и, возможно, в большинстве других) отключение предупреждения - плохая идея - оно существует не просто так.Другая альтернатива (сделать все строки доступными для записи по умолчанию) потенциально неэффективна.
Послушайте, что говорит вам компилятор!
просто используйте опцию -w для g ++
пример:
g ++ -w -o простой.o simple.cpp -lpthread
Помните, что это не позволяет избежать устаревания, скорее это предотвращает отображение предупреждающего сообщения на терминале.
Теперь, если вы действительно хотите избежать устаревания, используйте ключевое слово const следующим образом:
const char* s="constant string";
Почему бы вам не воспользоваться -Wno-deprecated
возможность игнорировать устаревшие предупреждающие сообщения?
Проблема прямо сейчас в том, что я работаю с -Werror
Это твоя настоящая проблема, ИМО.Вы можете попробовать несколько автоматизированных способов перехода от (char *) к (const char *), но я бы поставил деньги на то, чтобы они не просто работали.Вам придется привлечь человека хотя бы к части этой работы.На короткий срок просто игнорируйте предупреждение (но ИМО оставьте его включенным, иначе оно никогда не будет исправлено) и просто удалите -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 }
Я знаю, что в массиве сервера времени есть только 1 элемент.Но могло быть и нечто большее.Остальные пока были закомментированы, чтобы сэкономить память.
Ответ 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;
}
PyTypeObject PyDict_Type=
{ ...
PyTypeObject PyDict_Type=
{
PyObject_HEAD_INIT(&PyType_Type),
"dict",
dict_print,
0,
0
};
следите за полем name, в gcc оно компилируется без предупреждения, но в g ++ это произойдет, я не знаю почему.
в gcc (Compiling C)
, -Wno-write-strings активен по умолчанию.
в g++ (Compiling C++)
-Wwrite-strings активен по умолчанию
Вот почему существует другое поведение.Для нас, использующих макросы Boost_python
генерирует такие предупреждения.Поэтому мы используем -Wno-write-strings
при компиляции C ++, поскольку мы всегда используем -Werror