Link to home
Start Free TrialLog in
Avatar of anAppBuilder
anAppBuilderFlag for United States of America

asked on

How do I avoid the warning "deprecated conversion from string constant to char*"?

I actually want to do the correct conversion, not hide the warning in the compiler.  The code uses a lot of functions that I didn't write and can't really change, so I just want to do the right conversion in the call.   Is the approach in the attached code a good solution or am I missing a better way?
cppStingToCharStar.cpp
Avatar of jkr
jkr
Flag of Germany image

You don't need a function for that, 'string::c_str()' already does what you need - e.g.

int main ()
{
	//This call gets the warning
	someFcn("foo", "bar");

	string s1 = "foo", string s2 = "bar";
	someFcn(s1.c_str(), s2.c_str());

	return 0;
}

Open in new window


See also http://www.cplusplus.com/reference/string/string/c_str/
Avatar of anAppBuilder

ASKER

Well, yes.  That's exactly what my function does--it calls c_str().  I guess the question is which is more hassle.  Settiing up a C++ string for each parameter I pass or calling the function on the literal string for theparameter.
That depends on your setup - if you already have the parameters in C style strings, why addinf a layer of 'std::strings'. If it is mainly about string literals, my advice would be short: Keep 'em. There is no need to wrap a constant in another class,
Yes, but the string literal is hitting a deprecated feature.  And I think the deprecated conversion is going away in C++ 11.  So I want to be proactive
I am pretty positive that there won't be any changes in C++ that would really affect a C-style 'const char*' (since that would not just mean to shoot oneself in the foot, but rather severing that limb beforehand, just to stay within the picture)
This is not a const char* conversion.  That's the problem--it's char * conversion.

OK I kept digging and found this link

Apparently
char* p = "abc"; // valid in C, invalid in C++

Open in new window

char* p = (char*)"abc"; // OK: cast added

Open in new window

So a better soluion is to use the cast.
SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you, jkr  No there are no warnings in that case,  but I do not get to fix "someFcn".  There are many "someFcn's"  in many many lines of legacy code. Nobody is going to go back and fix that legacy code. Note also that the code I am writing is C++ and uses char* or const char* only when I need to call the legacy C code.

This question is about how to deal with many "someFcn's" in legacy code.   In many cases programmers used char* instead of const char* in many input arguments to functions.  Maybe those char*'s get changed in the called function, but they are not used to return anything.  

So is it reasonable just to cast the literal strings to char*? Or is that going to cause some other problem like memory leaks?
someFcn((char*)"foo", (char*)"bar");

Open in new window

Yes, that would be th eother way round, and work as well. But as you have many of functions like that, you most likely are going to have many calls, so adapting them to use correct casts is probably as tedious. As I wrote earlier, just ignore that error or set your compiler to do that. At least that was my conclusion when I encountered it first a while ago.
Thank you, phoffric and jkr.

As I am mostly writing new code, adding the type casts is pretty staight forward. One more quesion--what is the difference between these two ways of casting? And why would one be better or worse?

(char*)"foo"
const_cast<char*>("foo")
In the end, there is no difference. The 1st one is the C and C++ way of casting (with the emphasis on C) and the latter is the strictly C++ way of casting. One difference is that a C++-style cast could throw an exception at runtime (well, not a 'const_cast<>()', though).
Thank you again, jkr.  One more question.  Does the C++ style cast force the compiler not re-use literals.  If for some reason someFcn actually changes its input arguments, is the C++ style safer?
//Per porffic this does not force the compiler 
//to store the 2 instances of "foo" separately
//so "foo" could be changed for the second call

somefcn1((char*)"foo");
somefcn2((char*)"foo");


//Does this force separate storage of the 2 "foo"s?

somefcn1(const_cast<char*>("foo"));
someFcn2(const_cast<char*>("foo"));

Open in new window

Avatar of phoffric
phoffric

True, in this case, both types of casts result in the same thing - removing the const-ness from the literal string constant. The best practice is to use the C++ cast mechanisms, in general, as this approach provides better compiler checks. These C++ casts are also more self-documenting. When using const_cast<char*>("foo"), it is clear to the reader that you are just changing the const-ness. With the C-Style cast, you should add a comment that you are just removing the const-ness.

It is easier to search for specific types of casts using C++ casting. If a developer were to change their api to include a const, then finding the appropriate casts that are no longer needed becomes easier.
>> Does the C++ style cast force the compiler not re-use literals.  If for some reason someFcn actually changes its input arguments, is the C++ style safer?

There is nothing in the C++ specification that requires a "forcing" as you might hope. Neither cast is safer with respect to modifying literals.
It is up to the compiler to decide whether two usages of "foo" will be two different memory locations or not, and whether those locations are in read-only pages (which is a reasonable expectation, and desirable for truly const values).

If your program works under some non-standard assumptions, then it may stop working the same way if you upgrade your a compiler or platform. Keeping to the standard assures you an easier porting experience if either of those things happen in the future.
Thank you both!

There are really 2 soutions presented here.  

phoffric presents the practical solution--how to handle calls to legacy code that is not going to be fixed (changed from char* to const char*).

jkr gives the "right" solution, the way the legacy code should have been written.