rezaebrh
rezaebrh

Reputation: 431

boost::lexical_cast wrong output

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

Live sample

Upvotes: 7

Views: 711

Answers (2)

Zan Lynx
Zan Lynx

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

Silvio Mayolo
Silvio Mayolo

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

Related Questions