419
votes

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?

23
When you do come to tackle replacing 554 lines, sed is a good friend. Make sure you back up first though.hookenz
I looked at the discussions about how to suppress the error messages and what the correct replacements should be. I don't have any opinions about that. However, I think that Matt is on the right track. Define what you want to replace by what. You just need the right regular expression(s). Make the changes in a copy. Use "diff" to compare them with the original. Making the changes using sed is quick, easy and free, and diff is also quick, easy and free. Try it and see how many changes you have to review. Post what you want to replace by what, and let users suggest regex replacements.Thomas Hedden
The entire discussion is missing the point of why this is a problem that needs fixing at all according to the gcc warning. The reason is in David Schwartz' answer stackoverflow.com/questions/56522654/….andig
564 files is entirely doable. Just do it. (Well, in all likelihood you have done it by now ;-) ).Peter - Reinstate Monica

23 Answers

237
votes

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

571
votes

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

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).

68
votes

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.

33
votes

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.

27
votes

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
27
votes

Replace

char *str = "hello";

with

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

or if you are calling in function:

foo("hello");

replace this with

foo((char*) "hello");
25
votes

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

char *setf = tigetstr("setf");

to this:

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

Instead of:

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

This works:

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

In C++, use the const_cast as like below

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

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

char str[] = "Test string";

or:

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

Why not just use type casting?

(char*) "test"
2
votes

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

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

In C++, Replace:

char *str = "hello";

with:

std::string str ("hello");

And if you want to compare it:

str.compare("HALLO");
1
votes

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.

0
votes

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.

0
votes

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!

0
votes

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";  
0
votes

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

0
votes

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.

0
votes

While passing string constants to functions write it as:

void setpart(const char name[]);

setpart("Hello");

instead of const char name[], you could also write const char \*name

It worked for me to remove this error:

[Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings]
-1
votes
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

-1
votes

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.