Come eliminare gli avvisi di "conversione deprecata dalla costante di stringa a" char* "in GCC?
Domanda
Quindi sto lavorando su una codebase estremamente ampia e recentemente aggiornato a gcc 4.3, che ora attiva questo avviso:
avvertimento:conversione deprecata dalla costante stringa a "char*"
Ovviamente, il modo corretto per risolvere questo problema è trovare ogni dichiarazione like
char *s = "constant string";
o chiamata di funzione come:
void foo(char *s);
foo("constant string");
e realizzarli const char
puntatori.Tuttavia, ciò significherebbe toccare almeno 564 file, che non è un compito che desidero eseguire in questo momento.Il problema in questo momento è che sto correndo -werror
, quindi ho bisogno di un modo per soffocare questi avvertimenti.Come lo posso fare?
Soluzione
Credo che passi -Wno-write-strings
to gcc sopprimerà questo avviso.
Altri suggerimenti
Qualsiasi funzione a cui passi valori letterali stringa "I am a string literal"
dovrebbe usare char const *
come tipo invece di char*
.
Se hai intenzione di aggiustare qualcosa, aggiustala bene.
Spiegazione:
Non è possibile utilizzare valori letterali stringa per inizializzare le stringhe che verranno modificate, perché sono di tipo const char*
.Gettare via la consistenza per modificarle in seguito lo è comportamento indefinito, quindi devi copiare il tuo const char*
stringhe char
di char
in allocato dinamicamente char*
stringhe per modificarle.
Esempio:
#include <iostream>
void print(char* ch);
void print(const char* ch) {
std::cout<<ch;
}
int main() {
print("Hello");
return 0;
}
Dai un'occhiata a GCC Pragma diagnostico supporto e l'elenco dei -W opzioni di avviso (cambiato: nuovo collegamento alle opzioni di avviso).
Per gcc, puoi usare #pragma warning
direttive come spiegato Qui.
Ho avuto un problema simile, l'ho risolto in questo modo:
#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);
}
È questo un modo appropriato per risolvere questo problema?Non ho accesso a foo
adattarlo per accettare const char*
, anche se sarebbe una soluzione migliore (perché foo
non cambia m
).
Se si tratta di una codebase attiva, potresti comunque voler aggiornare la codebase.Naturalmente, eseguire le modifiche manualmente non è fattibile, ma credo che questo problema possa essere risolto una volta per tutte con un unico sed
comando.Non l'ho provato, però, quindi prendi quanto segue con le pinze.
find . -exec sed -E -i .backup -n \
-e 's/char\s*\*\s*(\w+)\s*= "/char const* \1 = "/g' {} \;
Questo potrebbe non trovare tutti i posti (anche senza considerare le chiamate di funzione) ma allevierebbe il problema e consentirebbe di eseguire manualmente le poche modifiche rimanenti.
Non riesco a utilizzare l'opzione del compilatore.Quindi ho trasformato questo:
char *setf = tigetstr("setf");
a questa:
char *setf = tigetstr((char *)"setf");
Ecco come farlo in linea in un file, quindi non devi modificare il tuo Makefile.
// gets rid of annoying "deprecated conversion from string constant blah blah" warning
#pragma GCC diagnostic ignored "-Wwrite-strings"
Potrai quindi più tardi...
#pragma GCC diagnostic pop
Sostituire
char *str = "hello";
con
char *str = (char*)"hello";
o se stai chiamando in funzione:
foo("hello");
sostituiscilo con
foo((char*) "hello");
Invece di:
void foo(char *s);
foo("constant string");
Funziona:
void foo(const char s[]);
foo("constant string");
In C++, utilizzare il const_cast
come sotto
char* str = const_cast<char*>("Test string");
Test string
è const stringa.Quindi puoi risolvere in questo modo:
char str[] = "Test string";
O:
const char* str = "Test string";
printf(str);
Perché non usare semplicemente il casting del tipo?
(char*) "test"
Esegui il typecasting dalla stringa costante al puntatore al carattere, ad es.
char *s = (char *) "constant string";
In C++, sostituisci:
char *str = "hello";
con:
std::string str ("hello");
E se vuoi fare un confronto:
str.compare("HALLO");
Non capisco come applicare la tua soluzione :( – kalmanIsAGameChanger
Lavorando con Arduino Sketch, avevo una funzione che causava i miei avvisi.
Funzione originale:char StrContains(char *str, char *sfind)
Per interrompere gli avvisi ho aggiunto il file cost davanti al carattere *str e al carattere *sfind.
Modificata:char StrContains(const char *str, const char *sfind).
Tutti gli avvertimenti sono scomparsi.
vedi questa situazione:
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
};
guarda il campo del nome, in gcc si compila senza preavviso, ma in g++ lo farà, non so perché.
È inoltre possibile creare una stringa scrivibile da una costante stringa chiamando strdup()
.
Ad esempio, questo codice genera un avviso:
putenv("DEBUG=1");
Tuttavia, il codice seguente non lo fa (crea una copia della stringa sull'heap prima di passarla a putenv
):
putenv(strdup("DEBUG=1"));
In questo caso (e forse nella maggior parte degli altri) disattivare l'avviso è una cattiva idea: è lì per un motivo.L'altra alternativa (rendere tutte le stringhe scrivibili per impostazione predefinita) è potenzialmente inefficiente.
Ascolta cosa ti dice il compilatore!
usa semplicemente l'opzione -w per g++
esempio:
g++ -w -o semplice.o semplice.cpp -lpthread
Ricorda che questo non evita la deprecazione, piuttosto impedisce la visualizzazione di messaggi di avviso sul terminale.
Ora, se vuoi davvero evitare la deprecazione, usa la parola chiave const come questa:
const char* s="constant string";
Perché non usi il -Wno-deprecated
opzione per ignorare i messaggi di avviso deprecati?
Il problema in questo momento è che sto utilizzando -Werror
Questo è il tuo vero problema, IMO.Puoi provare alcuni modi automatizzati per passare da (char *) a (const char *), ma ci metterei dei soldi non solo per farli funzionare.Dovrai coinvolgere un essere umano almeno per parte del lavoro.Per il breve termine, ignora semplicemente l'avviso (ma IMO lascialo attivo, altrimenti non verrà mai risolto) e rimuovi semplicemente -Werror.
Grazie a tutti per l'aiuto.Scegliendo di qua e di là arriva questa soluzione.Questo compila pulito.Non ho ancora testato il codice.Domani...Forse...
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 }
Lo so, c'è solo 1 elemento nell'array timeServer.Ma potrebbe esserci di più.Il resto è stato commentato per ora per risparmiare memoria.
La risposta di BlackShift è molto utile e l'ho usata in questo modo:
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
};
guarda il campo del nome, in gcc si compila senza preavviso, ma in g++ lo farà, non so perché.
In gcc (Compiling C)
, -Wno-write-strings è attivo per impostazione predefinita.
In g++ (Compiling C++)
-Wwrite-strings è attivo per impostazione predefinita
Ecco perché c'è un comportamento diverso.Per noi che utilizziamo le macro di Boost_python
genera tali avvisi.Quindi usiamo -Wno-write-strings
quando compiliamo C++ poiché usiamo sempre -Werror