Como se livrar dos avisos de `conversão obsoleta de constante de string para 'char *'` no GCC?

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

  •  09-06-2019
  •  | 
  •  

Pergunta

Estou trabalhando em uma base de código extremamente grande e atualizei recentemente para o gcc 4.3, que agora aciona este aviso:

aviso:conversão obsoleta de constante de string para ‘char*’

Obviamente, a maneira correta de corrigir isso é encontrar todas as declarações como

char *s = "constant string";

ou chamada de função como:

void foo(char *s);
foo("constant string");

e fazê-los const char ponteiros.No entanto, isso significaria tocar em 564 arquivos, no mínimo, o que não é uma tarefa que desejo realizar neste momento.O problema agora é que estou correndo com -werror, então preciso de alguma maneira de reprimir esses avisos.Como eu posso fazer isso?

Foi útil?

Solução

Eu acredito que passando -Wno-write-strings para gcc suprimirá este aviso.

Outras dicas

Quaisquer funções para as quais você passa literais de string "I am a string literal" Deveria usar char const * como o tipo em vez de char*.

Se você vai consertar alguma coisa, conserte direito.

Explicação:

Você não pode usar literais de string para inicializar strings que serão modificadas, porque elas são do tipo const char*.Jogar fora a constância para depois modificá-las é comportamento indefinido, então você tem que copiar seu const char* cordas char por char em alocado dinamicamente char* strings para modificá-las.

Exemplo:

#include <iostream>

void print(char* ch);

void print(const char* ch) {
    std::cout<<ch;
}

int main() {
    print("Hello");
    return 0;
}

Confira o gcc Pragma Diagnóstico suporte e a lista de -W opções de aviso (mudado: novo link para opções de aviso).

Para gcc, você pode usar #pragma warning diretivas como explicadas aqui.

Eu tive um problema semelhante, resolvi assim:

#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);
}

Esta é uma maneira apropriada de resolver isso?Eu não tenho acesso a foo adaptá-lo para aceitar const char*, embora essa fosse uma solução melhor (porque foo não muda m).

Se for uma base de código ativa, talvez você ainda queira atualizar a base de código.É claro que realizar as alterações manualmente não é viável, mas acredito que esse problema poderia ser resolvido de uma vez por todas com um único sed comando.Eu ainda não tentei, então considere o seguinte com cautela.

find . -exec sed -E -i .backup -n \
    -e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;

Isso pode não encontrar todos os locais (mesmo sem considerar as chamadas de função), mas aliviaria o problema e tornaria possível realizar manualmente as poucas alterações restantes.

Não consigo usar a opção do compilador.Então eu transformei isso:

char *setf = tigetstr("setf");

para isso:

char *setf = tigetstr((char *)"setf");

Aqui está como fazer isso embutido em um arquivo, para que você não precise modificar seu Makefile.

// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"

Você pode então mais tarde...

#pragma GCC diagnostic pop

Substituir

char *str = "hello";

com

char *str = (char*)"hello";

ou se você estiver chamando uma função:

foo("hello");

substitua isso por

foo((char*) "hello");

Em vez de:

void foo(char *s);
foo("constant string");

Isso funciona:

void foo(const char s[]);
foo("constant string");

Em C++, use o const_cast como abaixo

char* str = const_cast<char*>("Test string");

Test string é uma string const.Então você pode resolver assim:

char str[] = "Test string";

ou:

const char* str = "Test string";
printf(str);

Por que não usar apenas a conversão de tipos?

(char*) "test"

Faça a conversão de tipo de string constante para ponteiro de caractere, ou seja,

char *s = (char *) "constant string";

Em C++, substitua:

char *str = "hello";

com:

std::string str ("hello");

E se você quiser comparar:

str.compare("HALLO");

Não entendo como aplicar sua solução :( – kalmanIsAGameChanger

Trabalhando com o Arduino Sketch, tive uma função que causou meus avisos.

Função original:char StrContém(char *str, char *sfind)

Para interromper os avisos, adicionei o const na frente do char *str e do char *sfind.

Modificado:char StrContains(const char *str, const char *sfind).

Todos os avisos desapareceram.

veja esta situação:

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
};

observe o campo name, no gcc ele compila sem avisar, mas no g++ compilará, não sei por quê.

Você também pode criar uma string gravável a partir de uma constante de string chamando strdup().

Por exemplo, este código gera um aviso:

putenv("DEBUG=1");

No entanto, o código a seguir não (ele faz uma cópia da string no heap antes de passá-la para putenv):

putenv(strdup("DEBUG=1"));

Neste caso (e talvez na maioria dos outros), desligar o aviso é uma má ideia – ele existe por um motivo.A outra alternativa (tornar todas as strings graváveis ​​por padrão) é potencialmente ineficiente.

Ouça o que o compilador está lhe dizendo!

basta usar a opção -w para g++

exemplo:

g++ -w -o simples.o simples.cpp -lpthread

Lembre-se de que isso não evita a depreciação, mas evita a exibição de mensagens de aviso no terminal.

Agora, se você realmente deseja evitar a depreciação, use a palavra-chave const como esta:

const char* s="constant string";  

Por que você não usa o -Wno-deprecated opção para ignorar mensagens de aviso obsoletas?

O problema agora é que estou executando com -Werror

Este é o seu verdadeiro problema, IMO.Você pode tentar algumas maneiras automatizadas de passar de (char *) para (const char *), mas eu apostaria neles, não apenas no trabalho.Você terá que ter um humano envolvido em pelo menos parte do trabalho.No curto prazo, apenas ignore o aviso (mas deixe-o ativado na IMO ou nunca será corrigido) e apenas remova o -Werror.

Obrigado a todos pela ajuda.Escolhendo daqui e dali vem essa solução.Isso compila limpo.Ainda não testei o código.Amanhã...talvez...

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 }

Eu sei, há apenas 1 item na matriz timeServer.Mas poderia haver mais.O resto foi comentado por enquanto para economizar memória.

A resposta do BlackShift é muito útil e eu a usei como:

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
}; 

observe o campo name, no gcc ele compila sem avisar, mas no g++ compilará, não sei por quê.

em gcc (Compiling C), -Wno-write-strings está ativo por padrão.

em g++ (Compiling C++) -Wwrite-strings está ativo por padrão

É por isso que existe um comportamento diferente.Para nós, usando macros de Boost_python gera tais avisos.Então usamos -Wno-write-strings ao compilar C++, pois sempre usamos -Werror

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top