Sign in to follow this  
  • entries
    8
  • comments
    10
  • views
    9422

const char* to bool, not std::string(bug)

Sign in to follow this  
CTar

1177 views

I found a very strange bug in some of my code the other day, I isolated the problem to this:


#include
#include

void Print(bool P)
{
std::cout << P;
}
void Print(const std::string& P)
{
std::cout << P;
}

int main()
{
Print("test\n");
const std::string Tmp = "test\n";
Print(Tmp);

return 0;
}



What do you think this will output? I thought the output would be:

test
test


But the output (in both VC7.1 and VC8.0) is:


1test


In VS2005 the code compiles without a single error on the highest warning level (4). I did some debugging and figured out the bool overload was called with the first function call, and the std::string overload was called with the second function call. First when I tried to code in VS2003 I found the error, I got the warning:

\Main.cpp(15) : warning C4800: 'const char *' : forcing value to bool 'true' or 'false' (performance warning)

Then it quickly became clear that I was passing a const char*, I thought it would be converted to a std::string, but since a const char* is just a pointer it was converted to a boolean, true in this case because the address wasn't 0.

I fixed it by adding an overload taking const char*. So this is what happens when you think of const char* as a string, not a pointer and when you assume "test" is more likely to be converted to a string than a boolean value.
Sign in to follow this  


2 Comments


Recommended Comments

I've been nailed by that one before. In general, I've started using const char* parameters everywhere where I don't actually need an explicit string, and/or using string("string literal") to ensure that a string is always constructed from a literal when needed.

The alternative (which is useful for a different class of problems) is to store all string literals in a centralized area, like a string table resource or a header file. Then define a unified interface to accessing them, and use that instead of inlined hardcode strings. I started doing that mainly for localization purposes, but it proves handy in other areas as well.

Share this comment


Link to comment
Quote:

The alternative (which is useful for a different class of problems) is to store all string literals in a centralized area, like a string table resource or a header file. Then define a unified interface to accessing them, and use that instead of inlined hardcode strings. I started doing that mainly for localization purposes, but it proves handy in other areas as well.


As you say yourself there is also problems with this, others though. You could make the class look up the string with a recieved char* or you could look up the string yourself and send the string to whatever class needs it.

One problem with letting the class look up the string itself can be that the users of my library probably wont use a string table, and even if they do they probably wont use my approach.

A problem with letting the user of the class look up the string itself could be that when they dont want to look up the string they can't just pass a string literal.

So I would say the best solution would be too let the user pass a char* or a string and let the looking up strings be the user's resposibility, but your application might have other needs, but for a general purpose library I think this is the best approach (others I haven't heard of may exist).

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now