Как избавиться от `устаревшего преобразования из строковой константы в '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 возможность игнорировать устаревшие предупреждающие сообщения?

Другие вопросы по тегам