[Home] [Downloads] [Search] [Help/forum]

Gammon Forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  ROM
. -> [Folder]  Compiling the server
. . -> [Subject]  warning: deprecated conversion from string constant to 'char*'
Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?

warning: deprecated conversion from string constant to 'char*'

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Posted by Robert Powell   Australia  (367 posts)  [Biography] bio
Date Sat 24 Oct 2009 04:02 AM (UTC)
Message
Ok, does anyone have a proper solution to deal with warning: deprecated conversion from string constant to 'char*' warnings in G++ code other than suppressing the warning.

Thanks.

Just a guy having a bit of fun. Nothing more, nothing less, I do not need I WIN to feel validated.
[Go to top] top

Posted by Worstje   Netherlands  (899 posts)  [Biography] bio
Date Reply #1 on Sat 24 Oct 2009 05:48 AM (UTC)
Message
The solution depends on the situation.

A constant is a constant, and thus cannot be changed. A char* parameter is a pointer to a(n array of) char(s), and can thus be changed from within the function that has it as a parameter. Thus, if you feed it a constant, and it tries to modify it, you'll get a crazy-ass segfault.

If the function is not meant to be modifying what you pass to it, change the parameter to a const char* and the error will disappear.

If the function -is- meant to change what you pass to it, you simply can't pass a string constant to it. Allocating an array of chars and strcpy()-ing your constant into it, and then passing said array to the function is the other solution.
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Sat 24 Oct 2009 06:13 AM (UTC)

Amended on Sat 24 Oct 2009 06:14 AM (UTC) by Nick Gammon

Message
Well it isn't really valid to coerce "const char *" to "char *", particularly with string literals. For one thing, once it becomes char *, and pass it to a function, that function can validly change it. Now for a literal, which is likely to be shared amongst various places, this might result in changing "dog" to "cat" not just once, but everywhere in the program.

Another problem is that literals are likely to be in protected memory, so it will crash if you attempt to change it.

Basically, what you need to do is, if you are passing a literal down to a function, that function should be taking a const char * argument, not a char * argument.

However this can be fiddly to get right, as you then find that if this function calls other functions, they also need to be changed and you get a knock-on effect. Plus, sometimes you actually want to pass down char * data (eg. something the player types), so making it take the const form can then break other things.

If you are using C++ and not C, you might be able to use the string class to work around this. For example, instead of:


void my_func (char * s) { blah }


you might have:


void my_func (string s) { blah }


For example:


#include <iostream>
#include <string>

using namespace std;


void my_func (char * s)
  {
  cout << s << endl;
  }

int main (void)
{
  my_func ("nick");
  return 0;
}


Compiles with:


test1.cpp: In function ‘int main()’:
test1.cpp:14: warning: deprecated conversion from string constant to ‘char*’


However:


#include <iostream>
#include <string>
#include <string.h>

using namespace std;


void my_func (string s)
  {
  cout << s << endl;
  }

int main (void)
{
  char s1 [] = "hello there";
  char s2 [100];
  strcpy (s2, "testing");
  my_func ("nick");
  my_func (s1);
  my_func (s2);
  return 0;
}


That compiled without warnings, and printed all 3 strings. Once you have a string (as in, the string class) you can convert back to const char * with the c_str function. For example:


  string s3 = "test";
  printf ("%s\n", s3.c_str ());


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Robert Powell   Australia  (367 posts)  [Biography] bio
Date Reply #3 on Sat 24 Oct 2009 12:32 PM (UTC)
Message
Thanks Nick, that makes a whole lot of sense, the code i have been asked to look at and clean up has been somewhat converted to g++ and there are literally 1000's of these warnings.

Ultimately this looks like a rock and a hard place situation where i am going to have to spend hours fixing each and every location, how you mentioned it above.

Just a guy having a bit of fun. Nothing more, nothing less, I do not need I WIN to feel validated.
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #4 on Mon 26 Oct 2009 02:39 AM (UTC)
Message
You can look at what I did for SmaugFUSS to fix these warnings. It's a little tedious, but basically you need to make sure that if a function doesn't modify a char* argument, that the argument becomes a const char*. If the function absolutely must modify it, you should see if you can get away with a temporary local copy, or if the caller should be taking care of passing in a modifiable copy. For the vast majority of cases, it's quite clear what you need to change; there are just a handful of places where you need to be careful, typically in making sure that you create and destroy temporary copies appropriately.

If you're going to take the std::string approach, your parameters should be const std::string&, not just std::string. Although it makes no difference if you're passing in char* pointers -- the std::string must be constructed regardless -- it will make a difference if/when you have more std::strings lying around, because you will not be needlessly copying them.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Robert Powell   Australia  (367 posts)  [Biography] bio
Date Reply #5 on Mon 26 Oct 2009 03:33 AM (UTC)
Message
Thanks David, i have not actually begun on this part of my G++ ROM odyssey as im am a little apprehensive when it comes to making wholesale changes that i don't really understand.

I think which keeping with the G++ experience i would end up going down the std::string path, as it may serve me better in the long run, for now i have suppressed the warnings, however i would like to look at some sample code that has done this already, do you have any suggestions that i should look at.

Just a guy having a bit of fun. Nothing more, nothing less, I do not need I WIN to feel validated.
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #6 on Mon 26 Oct 2009 04:30 AM (UTC)
Message
Yes. As I said, I went through the SmaugFUSS code and fixed these warnings by handling constness correctly. You can simply look at the most recent version of SmaugFUSS to see how constness was respected; a lot of the code overlaps with ROM as far as I know.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #7 on Mon 26 Oct 2009 04:40 AM (UTC)
Message
I didn't use the & feature (ie. make it pass by reference) because I wasn't sure a literal string would be converted to a reference, but it appears David is right. You can change the function in my example to:


void my_func (const string & s)
  {
  cout << s << endl;
  }


That still compiles and runs OK. (Not sure why, perhaps the compiler makes a temporary string object on the stack, and passes that by reference).

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Mon 26 Oct 2009 04:43 AM (UTC)
Message
Robert Powell said:

I think which keeping with the G++ experience i would end up going down the std::string path, as it may serve me better in the long run ...


Yes, using the string class instead of char arrays saves a lot of stuff like:


char buf[MSL];


... which is basically allocating large strings all over the place "just in case" someone passes a long string into it. And still it might fail if the string coming in is larger than MSL. Using the string class is more efficient for small cases, and won't fail for large ones.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #9 on Mon 26 Oct 2009 04:45 AM (UTC)
Message
And technically, the language is C++, the compiler is the g++ compiler (note capitalisation).

From the man page (man g++) it says:


 gcc - GNU project C and C++ compiler


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #10 on Mon 26 Oct 2009 04:48 AM (UTC)
Message
Nick Gammon said:
(Not sure why, perhaps the compiler makes a temporary string object on the stack, and passes that by reference).

Yes, exactly. When you have a function f:


void f(SomeType arg) { ... }


and then you call it:


SomeOtherType val;
f(val);


then the compiler will try to convert SomeOtherType to SomeType, which can mean calling a SomeType constructor that takes a SomeOtherType as an argument. In this case, std::string has a const char* constructor, so the compiler calls that. The newly-constructed object is discarded once the call is complete. In this case, the temporary object is constructed, and then passed by reference, and finally destroyed.

This is one reason why it's occasionally good to have versions of a function for likely input parameters (e.g., const char* and std::string) because if you can avoid creating the std::string, you should (assuming efficiency matters in the context).

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #11 on Mon 26 Oct 2009 05:24 AM (UTC)

Amended on Mon 26 Oct 2009 05:51 AM (UTC) by Nick Gammon

Message
By which David means this could work for you:


#include <string>
#include <string.h>

using namespace std;

void my_func (const char * s)
{
  printf ("I got %s\n", s);
}

void my_func (const string & s)
{
  my_func (s.c_str ());
}

int main (void)
{
  char s1 [] = "hello there";
  char s2 [100];
  strcpy (s2, "testing");
  my_func ("nick");
  my_func (s1);
  my_func (s2);
  return 0;
}


Now there are two my_func functions, one will take a const char *, and one a const string, depending on what is required.

Interestingly, when I added a debugging line, all of the calls used the first my_func, so the compiler must have decided to convert char* to const char* rather than const string &.

I suppose this is because it is alright to add const-ness, but not to take it away.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #12 on Mon 26 Oct 2009 01:14 PM (UTC)
Message
Yeah, there are a series of rules about which conversions to prefer. I don't remember the exact phrasing of the rule, but it has to do with making the least amount of changes. Exact matches are preferred, and then "nearer" matches are preferred. So adding constness is "closer" than converting to another type (which makes sense really). But IIRC if it could be converted to two types, the compiler will complain about an ambiguous overload.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


14,625 views.

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at FutureQuest]