How to get rid of `deprecated conversion from stri

2019-01-01 12:14发布

问题:

So I\'m working on an exceedingly large codebase, and recently upgraded to gcc 4.3, which now triggers this warning:

warning: deprecated conversion from string constant to ‘char*’

Obviously, the correct way to fix this is to find every declaration like

char *s = \"constant string\";

or function call like:

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

and make them const char pointers. However, that would mean touching 564 files, minimum, which is not a task I wish to perform at this point in time. The problem right now is that I\'m running with -werror, so I need some way to stifle these warnings. How can I do that?

回答1:

I believe passing -Wno-write-strings to gcc will suppress this warning.



回答2:

Any functions into which you pass string literals \"I am a string literal\" should use char const * as the type instead of char*.

If you\'re going to fix something, fix it right.

Explanation:

You can not use string literals to initialise strings that will be modified, because they are of type const char*. Casting away the constness to later modify them is undefined behaviour, so you have to copy your const char* strings char by char into dynamically allocated char* strings in order to modify them.

Example:

#include <iostream>

void print(char* ch);

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

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


回答3:

Check out gcc\'s Diagnostic Pragma support, and the list of -W warning options (changed: new link to warning options).

For gcc, you can use #pragma warning directives like explained here.



回答4:

I had a similar problem, I solved it like this:

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

Is this an appropriate way of solving this? I do not have access to foo to adapt it to accept const char*, although that would be a better solution (because foo does not change m).



回答5:

If it\'s an active code base, you might still want to upgrade the code base. Of course, performing the changes manually isn\'t feasible but I believe that this problem could be solved once and for all by one single sed command. I haven\'t tried it, though, so take the following with a grain of salt.

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

This might not find all places (even not considering function calls) but it would alleviate the problem and make it possible to perform the few remaining changes manually.



回答6:

I can\'t use the compiler switch. So I have turned this:

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

to this:

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


回答7:

Here is how to do it inline in a file, so you don\'t have to modify your Makefile.

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

You can then later...

#pragma GCC diagnostic pop


回答8:

Replace

char *str = \"hello\";

with

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

or if you are calling in function:

foo(\"hello\");

replace this with

foo((char*) \"hello\");


回答9:

Instead of:

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

This works:

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


回答10:

In C++, use the const_cast as like below

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


回答11:

Test string is const string. So you can solve like this:

char str[] = \"Test string\";

or:

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


回答12:

Why not just use type casting?

(char*) \"test\"


回答13:

Do typecasting from constant string to char pointer i.e.

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


回答14:

You can also create a writable string from a string constant by calling strdup().

For instance, this code generates a warning:

putenv(\"DEBUG=1\");

However, the following code does not (it makes a copy of the string on the heap before passing it to putenv):

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

In this case (and perhaps in most others) turning off the warning is a bad idea -- it\'s there for a reason. The other alternative (making all strings writable by default) is potentially inefficient.

Listen to what the compiler is telling you!



回答15:

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

watch the name field, in gcc it compile without warning, but in g++ it will, i don\'t know why.



回答16:

In C++, Replace:

char *str = \"hello\";

with:

std::string str (\"hello\");

And if you want to compare it:

str.compare(\"HALLO\");


回答17:

I don\'t understand how to apply your solution :( – kalmanIsAGameChanger

Working with Arduino Sketch, I had a function causing my warnings.

Original function: char StrContains(char *str, char *sfind)

To stop the warnings I added the const in front of the char *str and the char *sfind.

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

All warnings went away.



回答18:

just use -w option for g++

example:

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

Remember this doesn\'t avoid deprecation rather it prevents showing warning message on the terminal.

Now if you really want to avoid deprecation use const keyword like this:

const char* s=\"constant string\";  


回答19:

Why don\'t you use the -Wno-deprecated option to ignore deprecated warning messages?



回答20:

BlackShift\'s answer is very helpful, and I used it like:

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


回答21:

The problem right now is that I\'m running with -Werror

This is your real problem, IMO. You can try some automated ways of moving from (char *) to (const char *) but I would put money on them not just working. You will have to have a human involved for at least some of the work. For the short term, just ignore the warning (but IMO leave it on, or it\'ll never get fixed) and just remove the -Werror.



回答22:

Thanks, all, for the help. Picking from here and there comes this solution. This compiles clean. Have not tested the code yet. Tomorrow... maybe...

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 }

I know, there\'s only 1 item in the timeServer array. But there could be more. The rest were commented out for now to save memory.



回答23:

PyTypeObject PyDict_Type=
{ ...

PyTypeObject PyDict_Type=
{
  PyObject_HEAD_INIT(&PyType_Type),
                     \"dict\",
                     dict_print,
                     0,
                     0
}; 

watch the name field, in gcc it compile without warning, but in g++ it will, i don\'t know why.

in gcc (Compiling C), -Wno-write-strings is active by default.

in g++ (Compiling C++) -Wwrite-strings is active by default

This is why there is a different behaviour. For us using macros of Boost_python generates such warnings. So we use -Wno-write-strings when compiling C++ since we always use -Werror



标签: c++ string gcc