Reputation: 431
Output of boost::lexical_cast
with a bool
variable as input is expected to be a 0
or 1
value. But I get different value instead.
It's not something which happen normally. Let's take a look at example code I've wrote:
#include <string>
#include <boost/lexical_cast.hpp>
int main()
{
bool alfa = true; // Doesn't metter whether alfa is initialized at definition or not
char beta = 71; // An integer value. Different values don't make any differences.
memcpy(&alfa, &beta, sizeof(alfa));
printf("%s\n", boost::lexical_cast<std::string>(alfa).c_str());
}
From this code, I've got "w"
(ASCII code of w is 71) as output! But I expected it to be a 0
or 1
value.
The problem is just the value that bool
variable will cast into. The bool
variable in the given example is already considered true.
What causes problem is imagine I want to convert back the converted value. That's where it throws exception because for example "w" character can't be converted to bool
. But if the output was 0
or 1
, re-conversion would be possible.
std::string converted_value = boost::lexical_cast<std::string>(alfa);
bool reconverted_value = boost::lexical_cast<bool>(converted_value ); // In this line, boost::bad_lexical_cast will be thrown
I was wondering whether the output is right or this is a bug in boost::lexical_cast
?
Also when I was trying to do the same thing and cast the variable to int
, I faced boost::bad_lexical_cast
exception.
My boost version: 1.58
Upvotes: 7
Views: 711
Reputation: 54393
You broke the rules. What did you expect, that C++ would add useless code to your program to catch rule-breakers?
Boolean variables can only be 0 or 1, false or true. And they are, if you assign to them properly, according to the rules.
If you memcpy them or reinterpret_cast then the underlying implementation shows through. A bool
is a memory byte. If it somehow gets set to something other than 0 or 1 then there it is.
I'd have to double-check but I'm not even sure you are guaranteed that a bool is one byte. I think you can take a pointer to it. But if the hardware had some way to create a pointer to one bit, you could be quite surprised at what C++ did with that.
Upvotes: 1
Reputation: 70407
The C++ standard does not specify how a Boolean is stored in memory, only that there are two possible values: true
and false
. Now, on your machine, I presume these are stored, respectively, as 1
and 0
. The compiler is allowed to make assumptions, and in particular it's allowed to assume that these are going to be the only two values stored in a Boolean.
Thus, when boost::lexical_cast
sees a Boolean, it runs code that probably looks something like this (after optimization)
// Gross oversimplification
std::string lexical_cast(bool value) {
char res = '0' + (int)value;
return std::string(1, res);
}
If value
is 0
or 1
, this works fine and does what you want. However, you put a 71
into it. So we add the ASCII code of '0'
(48
) to 71
and get 119
, the ASCII code of 'w'
.
Now, I'm not a C++ standard expert, but I would guess that storing a non-standard value into a Boolean with memcpy
is undefined behavior. At the very least, your code is non-portable. Perhaps someone more versed in the standard can fill in the holes in my knowledge as far as that's concerned.
Upvotes: 8