Как избавиться от предупреждений `устаревшее преобразование из строковой константы в ‘символ *’ в GCC?

StackOverflow https://stackoverflow.com/questions/59670

  •  09-06-2019
  •  | 
  •  

Вопрос

Итак, я работаю над чрезвычайно большой кодовой базой и недавно обновлен до 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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top