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?
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;
}
I believe passing -Wno-write-strings
to gcc will suppress this warning.
#pragma GCC diagnostic ignored "-Wwrite-strings"
.
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
).
char **
in PyArg_ParseTupleAndKeywords
I do something like this: static char kw[][16] = {"mode", "name", "ip", "port"}; static char * kwlist[] = {kw[0], kw[1], kw[2], kw[3], NULL};
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.
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.
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
I can't use the compiler switch. So I have turned this:
char *setf = tigetstr("setf");
to this:
char *setf = tigetstr((char *)"setf");
Replace
char *str = "hello";
with
char *str = (char*)"hello";
or if you are calling in function:
foo("hello");
replace this with
foo((char*) "hello");
Instead of:
void foo(char *s);
foo("constant string");
This works:
void foo(const char s[]);
foo("constant string");
In C++, use the const_cast
as like below
char* str = const_cast<char*>("Test string");
Test string
is const string. So you can solve like this:
char str[] = "Test string";
or:
const char* str = "Test string";
printf(str);
Why not just use type casting?
(char*) "test"
strchr()
. The strchr()
function won't change the storage identified by the passed-in pointer, but it should have no reason to care about whether the caller will use the returned pointer to modify that storage.
Do typecasting from constant string to char pointer i.e.
char *s = (char *) "constant string";
In C++, Replace:
char *str = "hello";
with:
std::string str ("hello");
And if you want to compare it:
str.compare("HALLO");
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.
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.
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!
putenv()
is fraught — it is not a good choice of example (at least, not without a lot more discussion of what putenv()
does than there is in this answer). It's a whole separate discussion. (Note that the POSIX specification for the behaviour of putenv()
is problematic, based on the legacy implementations from before POSIX was defined.) IIRC, there was a bug in a recent (this millennium) release of GNU C Library that was related to putenv()
behaviour changing, and being changed back.)
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";
Why don't you use the -Wno-deprecated
option to ignore deprecated warning messages?
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.
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]
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
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.
Success story sharing
char *
/const char *
, so in that case I normally cast.char*
even for strings that will not be modified. If you take a parameter as achar const*
and pass it to a standard function taking achar*
you'll hit that. If the library function will not be manipulating the string, you may cast away theconst
.