Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::lexical_cast wrong output

Tags:

c++

boost

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

like image 483
rezaebrh Avatar asked Jun 10 '19 13:06

rezaebrh


1 Answers

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.

like image 200
Silvio Mayolo Avatar answered Sep 26 '22 09:09

Silvio Mayolo