Comment se débarrasser des avertissements de « conversion obsolète d'une constante de chaîne en « char* » dans GCC ?

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

  •  09-06-2019
  •  | 
  •  

Question

Je travaille donc sur une base de code extrêmement volumineuse et j'ai récemment mis à niveau vers gcc 4.3, qui déclenche désormais cet avertissement :

avertissement:conversion obsolète de la constante de chaîne en 'char*'

Évidemment, la bonne façon de résoudre ce problème est de rechercher chaque déclaration comme

char *s = "constant string";

ou appel de fonction comme :

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

et fais-les const char pointeurs.Cependant, cela signifierait toucher au minimum 564 fichiers, ce qui n’est pas une tâche que je souhaite effectuer à ce stade.Le problème en ce moment c'est que je cours avec -werror, j'ai donc besoin d'un moyen d'étouffer ces avertissements.Comment puis je faire ça?

Était-ce utile?

La solution

je crois qu'en passant -Wno-write-strings vers gcc supprimera cet avertissement.

Autres conseils

Toutes les fonctions dans lesquelles vous transmettez des littéraux de chaîne "I am a string literal" devrait utiliser char const * comme type au lieu de char*.

Si vous voulez réparer quelque chose, réparez-le correctement.

Explication:

Vous ne pouvez pas utiliser de chaînes littérales pour initialiser des chaînes qui seront modifiées, car elles sont de type const char*.Se débarrasser de la constance pour les modifier ultérieurement est comportement indéfini, vous devez donc copier votre const char* cordes char par char en allocation dynamique char* chaînes afin de les modifier.

Exemple:

#include <iostream>

void print(char* ch);

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

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

Découvrez les gcc Pragme diagnostique soutien et la liste des -W options d'avertissement (modifié: nouveau lien vers les options d'avertissement).

Pour gcc, vous pouvez utiliser #pragma warning directives comme expliqué ici.

J'ai eu un problème similaire, je l'ai résolu comme ceci :

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

Est-ce une manière appropriée de résoudre ce problème ?je n'ai pas accès à foo l'adapter pour accepter const char*, même si ce serait une meilleure solution (car foo ne change pas m).

S'il s'agit d'une base de code active, vous souhaiterez peut-être toujours mettre à niveau la base de code.Bien sûr, effectuer les modifications manuellement n'est pas réalisable, mais je pense que ce problème pourrait être résolu une fois pour toutes par un seul sed commande.Cependant, je ne l'ai pas essayé, alors prenez ce qui suit avec des pincettes.

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

Cela pourrait ne pas trouver tous les emplacements (même sans tenir compte des appels de fonction), mais cela atténuerait le problème et permettrait d'effectuer manuellement les quelques modifications restantes.

Je ne peux pas utiliser le commutateur du compilateur.J'ai donc transformé ceci :

char *setf = tigetstr("setf");

pour ça:

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

Voici comment le faire en ligne dans un fichier, afin de ne pas avoir à modifier votre Makefile.

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

Vous pourrez alors plus tard...

#pragma GCC diagnostic pop

Remplacer

char *str = "hello";

avec

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

ou si vous appelez une fonction :

foo("hello");

remplacez ceci par

foo((char*) "hello");

Au lieu de:

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

Cela marche:

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

En C++, utilisez le const_cast comme ci-dessous

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

Test string est une chaîne const.Vous pouvez donc résoudre comme ceci :

char str[] = "Test string";

ou:

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

Pourquoi ne pas simplement utiliser le casting de type ?

(char*) "test"

Effectuez un transtypage d'une chaîne constante vers un pointeur de caractère, c'est-à-dire

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

En C++, remplacez :

char *str = "hello";

avec:

std::string str ("hello");

Et si tu veux comparer :

str.compare("HALLO");

Je ne comprends pas comment appliquer votre solution :( – kalmanIsAGameChanger

En travaillant avec Arduino Sketch, j'avais une fonction provoquant mes avertissements.

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

Pour arrêter les avertissements, j'ai ajouté le const devant le char *str et le char *sfind.

Modifié:char StrContains(const char *str, const char *sfind).

Tous les avertissements ont disparu.

voir cette situation:

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

surveillez le champ de nom, dans gcc, il compile sans avertissement, mais en g++, ce sera le cas, je ne sais pas pourquoi.

Vous pouvez également créer une chaîne inscriptible à partir d'une constante chaîne en appelant strdup().

Par exemple, ce code génère un avertissement :

putenv("DEBUG=1");

Cependant, le code suivant ne le fait pas (il fait une copie de la chaîne sur le tas avant de la transmettre à putenv):

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

Dans ce cas (et peut-être dans la plupart des autres), désactiver l’avertissement est une mauvaise idée : il est là pour une raison.L'autre alternative (rendre toutes les chaînes accessibles en écriture par défaut) est potentiellement inefficace.

Écoutez ce que le compilateur vous dit !

utilisez simplement l'option -w pour g++

exemple:

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

N'oubliez pas que cela n'évite pas la dépréciation, mais empêche l'affichage d'un message d'avertissement sur le terminal.

Maintenant, si vous voulez vraiment éviter la dépréciation, utilisez le mot-clé const comme celui-ci :

const char* s="constant string";  

Pourquoi n'utilises-tu pas le -Wno-deprecated option pour ignorer les messages d'avertissement obsolètes ?

Le problème en ce moment est que j'utilise -Werror

C'est votre vrai problème, OMI.Vous pouvez essayer des méthodes automatisées pour passer de (char *) à (const char *), mais je mettrais de l'argent dessus, pas seulement pour fonctionner.Vous devrez impliquer un humain pour au moins une partie du travail.À court terme, ignorez simplement l'avertissement (mais l'OMI le laisse activé, sinon il ne sera jamais corrigé) et supprimez simplement le -Werror.

Merci à tous pour votre aide.Choisir ici et là vient cette solution.Cela compile proprement.Je n'ai pas encore testé le code.Demain...peut être...

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 }

Je sais, il n'y a qu'un seul élément dans le tableau timeServer.Mais il pourrait y en avoir davantage.Le reste a été commenté pour l'instant pour économiser de la mémoire.

La réponse de BlackShift est très utile et je l'ai utilisée comme :

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

surveillez le champ de nom, dans gcc, il compile sans avertissement, mais en g++, ce sera le cas, je ne sais pas pourquoi.

dans gcc (Compiling C), -Wno-write-strings est actif par défaut.

dans g++ (Compiling C++) -Wwrite-strings est actif par défaut

C'est pourquoi il y a un comportement différent.Pour nous utilisant des macros de Boost_python génère de tels avertissements.Nous utilisons donc -Wno-write-strings lors de la compilation de C++ puisque nous utilisons toujours -Werror

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top