Ответ 1
Я считаю, что передача -Wno-write-strings
в 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 Диагностическая поддержка Pragma и список -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");
Вот как сделать это inline в файле, поэтому вам не нужно изменять свой 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");
В С++ используйте const_cast
, как показано ниже
char* str = const_cast<char*>("Test string");
Test string
- строка const. Поэтому вы можете решить вот так:
char str[] = "Test string";
или
const char* str = "Test string";
printf(str);
Почему бы просто не использовать литье типов?
(char*) "test"
Производится ли приведение типов с постоянной строкой в указатель char i.e.
char *s = (char *) "constant string";
В C++ заменить:
char *str = "hello";
с:
std::string str ("hello");
И если вы хотите сравнить это:
str.compare("HALLO");
Я не понимаю, как применить ваше решение :( - kalmanIsAGameChanger
Работая с Arduino Sketch, у меня была функция, вызывающая мои предупреждения.
Original function: char StrContains(char *str, char *sfind)
Чтобы прекратить предупреждения, я добавил const перед char * str и char * sfind.
Modified: char StrContains(const char *str, const char *sfind).
Все предупреждения ушли.
Проблема прямо сейчас в том, что я запускаю с -Werror
Это твоя настоящая проблема, ИМО. Вы можете попробовать несколько автоматических способов перехода от (char *) к (const char *), но я бы поместил на них деньги не просто. Вам нужно будет вовлечь человека, по крайней мере, в часть работы. В краткосрочной перспективе просто игнорируйте предупреждение (но IMO оставьте его, или он никогда не будет исправлен) и просто удалите -Werror.
Почему вы не используете параметр -Wno-deprecated
для игнорирования устаревших предупреждающих сообщений?
Вы также можете создать записываемую строку из строковой константы, вызвав 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++ это будет, я не знаю почему.
просто используйте параметр -w для g++
Пример:
g++ -w -o simple.o simple.cpp -lpthread
Помните, что это не исключает устаревания, а предотвращает показ предупреждающего сообщения на терминале.
Теперь, если вы действительно хотите избежать использования устаревания, используйте ключевое слово const:
const char* s="constant string";
Спасибо, все, за помощь. Выбор отсюда и там приходит это решение. Это компилируется. Еще не проверял код. Завтра... может быть...
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. Но может быть и больше. Остальные были закомментированы, чтобы сохранить память.
Ответ 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;
}
Объявление строки как 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-строки по умолчанию активны.
в g++ (Compiling C++)
-Wwrite-строки по умолчанию активны
Вот почему существует другое поведение.
Для нас использование макросов Boost_python
генерирует такие предупреждения.
Поэтому мы используем -Wno-write-strings
при компиляции С++, так как мы всегда используем -Werror