Come sbarazzarsi di `conversione deprecata da costante di stringa a ‘char *’` avvisi in GCC?

Quindi sto lavorando su un codebase estremamente grande e recentemente aggiornato a gcc 4.3, che ora triggers questo avviso:

avviso: conversione deprecata dalla costante di stringa a ‘char *’

Ovviamente, il modo corretto per risolvere questo problema è trovare ogni dichiarazione come

char *s = "constant string"; 

o chiamata di funzione come:

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

e const char . Tuttavia, ciò significherebbe toccare 564 file, minimo, che non è un compito che desidero eseguire in questo momento. Il problema adesso è che sto usando -werror , quindi ho bisogno di un modo per soffocare questi avvertimenti. Come lo posso fare?

Credo che passare -Wno-write-strings a gcc sopprimerà questo avviso.

Qualsiasi funzione in cui passi letterali di stringa "I am a string literal" dovrebbe utilizzare char const * come tipo invece di char* .

Se hai intenzione di aggiustare qualcosa, risolvi il problema.

Spiegazione:

Non è ansible utilizzare stringhe letterali per inizializzare le stringhe che verranno modificate, poiché sono di tipo const char* . Lanciare la costanza per modificarli successivamente è un comportamento indefinito , quindi devi copiare il tuo const char* char per char in stringhe char* allocate dynamicmente per modificarle.

Esempio:

 #include using namespace std; void print(char *); void print(const char *ch) { cout< 

Controlla il supporto Gcc ‘s Diagnostic Pragma e l’elenco delle opzioni di avviso -W (modificate: nuovo link alle opzioni di avviso ).

Per gcc, puoi usare le direttive di #pragma warning come spiegato qui .

Ho avuto un problema simile, l’ho risolto in questo modo:

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

È un modo appropriato per risolvere questo? Non ho accesso a foo per adattarlo ad accettare const char* , anche se sarebbe una soluzione migliore (perché foo non cambia m ).

Se è una base di codice triggers, potresti comunque voler aggiornare il codice base. Ovviamente, eseguire le modifiche manualmente non è fattibile, ma credo che questo problema possa essere risolto una volta per tutte da un singolo comando sed . Non l’ho ancora provato, quindi prendi il seguente con un pizzico di sale.

 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 renderebbe ansible eseguire manualmente le poche modifiche rimanenti.

Non posso usare l’interruttore 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" 

Puoi poi dopo …

 #pragma GCC diagnostic pop 

Sostituire

 char *str = "hello"; 

con

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

o se stai chiamando in funzione:

 foo("hello"); 

sostituirlo con

 foo((char*) "hello"); 

Invece di:

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

Questo funziona:

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

In C ++, usa il const_cast come sotto

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

Test string è const string. Quindi puoi risolvere in questo modo:

 char str[] = "Test string"; 

o:

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

Perché non usare semplicemente il casting di tipo?

 (char*) "test" 

Esegui il typecasting dalla stringa costante al puntatore char, ad es

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

È inoltre ansible creare una stringa scrivibile da una costante di stringa chiamando strdup() .

Ad esempio, questo codice genera un avviso:

 putenv("DEBUG=1"); 

Tuttavia, il codice seguente non lo fa (fa una copia della stringa putenv prima di putenv a putenv ):

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

In questo caso (e forse nella maggior parte degli altri) distriggersre l’avviso è una ctriggers idea – è lì per un motivo. L’altra alternativa (rendere tutte le stringhe scrivibili per impostazione predefinita) è potenzialmente inefficiente.

Ascolta cosa ti sta dicendo il compilatore!

vedere 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 lo compila senza preavviso, ma in g ++ lo farà, non so perché.

Non capisco come applicare la soluzione 🙁 – kalmanIsAGameChanger

Lavorando con Arduino Sketch, ho avuto una funzione che causa i miei avvertimenti.

Funzione originale: char StrContains (char * str, char * sfind)

Per fermare gli avvertimenti ho aggiunto il const davanti a char * str e al char * sfind.

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

Tutti gli avvertimenti sono andati via.

basta usare l’opzione -w per g ++

esempio:

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

Ricorda che questo non evita la deprecazione, piuttosto impedisce di mostrare un messaggio 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 l’opzione -Wno-deprecated per ignorare i messaggi di avviso deprecati?

La risposta di BlackShift è molto utile e l’ho usata come:

 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 = "< 

Il problema adesso è che sto correndo con -Werror

Questo è il tuo vero problema, IMO. Puoi provare alcuni modi automatici di passare da (char *) a (const char *), ma io metterei dei soldi su di loro non solo lavorando. Dovrai coinvolgere un essere umano per almeno parte del lavoro. Per il breve termine, ignora semplicemente l’avviso (ma IMO lo lascia acceso, o non verrà mai risolto) e rimuovi solo -Werror.

Grazie a tutti per l’aiuto. Scegliere da qui e là viene questa soluzione. Questo compila pulito. Non ho ancora testato il codice. Forse domani…

 const char * timeServer[] = { "pool.ntp.org" }; // 0 - Worldwide #define WHICH_NTP 0 // Which NTP server name to use. ... sendNTPpacket(const_cast(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 potrebbero essercene di più. Il resto è stato commentato per ora per risparmiare memoria.

In C ++, sostituisci:

 char *str = "hello"; 

con:

 std::string str ("hello"); 

E se vuoi confrontarlo:

 str.compare("HALLO"); 
 PyTypeObject PyDict_Type= { ... PyTypeObject PyDict_Type= { PyObject_HEAD_INIT(&PyType_Type), "dict", dict_print, 0, 0 }; 

guarda il campo del nome, in gcc lo compila senza preavviso, ma in g ++ lo farà, non so perché.

in gcc (Compiling C) , -Wno-write-string è attivo per impostazione predefinita.

in g++ (Compiling C++) -Wwrite-string è attivo per impostazione predefinita

Questo è il motivo per cui esiste un comportamento diverso. Per noi usare le macro di Boost_python genera tali avvisi. Quindi usiamo -Wno-write-strings quando -Wno-write-strings C ++ poiché usiamo sempre -Werror