boost :: lexical_cast неправильный вывод - PullRequest
2 голосов
/ 10 июня 2019

Выход boost::lexical_cast с переменной bool, поскольку на входе ожидается значение 0 или 1.Но вместо этого я получаю другое значение.

Это не то, что обычно происходит.Давайте посмотрим на пример кода, который я написал:

#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());
}

Из этого кода я получил "w" (ASCII-код w равен 71) в качестве вывода!Но я ожидал, что это будет значение 0 или 1.

Проблема заключается только в значении , в которое переменная bool будет приведена .Переменная bool в данном примере уже считается истинной.Проблема в том, что я хочу преобразовать обратно преобразованное значение.Вот где он выдает исключение, потому что, например, символ "w" не может быть преобразован в bool.Но если бы вывод был 0 или 1, было бы возможно повторное преобразование.

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

Мне было интересно, правильный ли вывод или это ошибка в boost::lexical_cast?

Также, когда я пытался сделать то же самое и привести переменную к int, я столкнулся с boost::bad_lexical_cast исключением.

Моя версия буста: 1,58

Liveобразец

Ответы [ 2 ]

5 голосов
/ 10 июня 2019

Стандарт C ++ не определяет, как логическое значение хранится в памяти, только то, что есть два возможных значения: true и false. Теперь, на вашей машине, я предполагаю, что они хранятся соответственно как 1 и 0. Компилятору разрешено делать предположения, и, в частности, он может предполагать, что это будут единственные два значения, хранящиеся в логическом значении.

Таким образом, когда boost::lexical_cast видит логическое значение, он запускает код, который, вероятно, выглядит примерно так (после оптимизации)

// Gross oversimplification
std::string lexical_cast(bool value) {
  char res = '0' + (int)value;
  return std::string(1, res);
}

Если value равен 0 или 1, это прекрасно работает и делает то, что вы хотите. Тем не менее, вы положили 71 в него. Поэтому мы добавляем код ASCII '0' (48) к 71 и получаем 119, код ASCII 'w'.

Теперь я не эксперт по стандарту C ++, но я бы предположил, что сохранение нестандартного значения в логическое значение с memcpy - неопределенное поведение. По крайней мере, ваш код непереносим. Возможно, кто-то более сведущий в стандарте может заполнить пробелы в моих знаниях, насколько это касается.

1 голос
/ 10 июня 2019

Вы нарушили правила.Что вы ожидали, что C ++ добавит бесполезный код в вашу программу для перехвата нарушителей правил?

Булевы переменные могут быть только 0 или 1, false или true.И они равны , если вы назначите их правильно, в соответствии с правилами.

Если вы запомните их или reinterpret_cast, то базовая реализация проследит.bool - это байт памяти.Если он каким-то образом настроен на что-то, отличное от 0 или 1, тогда это так.

Мне придется перепроверить, но я даже не уверен, что вам гарантировано, что bool равен один байт.Я думаю, что вы можете взять указатель на это.Но если бы у оборудования был какой-то способ создать указатель на один бит, вы могли бы быть весьма удивлены тем, что C ++ сделал с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...