【问题标题】:boost::lexical_cast wrong outputboost::lexical_cast 错误输出
【发布时间】:2019-06-10 13:33:33
【问题描述】:

boost::lexical_cast 的输出以 bool 变量作为输入应为 01 值。但我得到了不同的价值。

这不是正常发生的事情。让我们看一下我写的示例代码:

#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"(w 的 ASCII 代码为 71)作为输出!但我希望它是 01 值。

问题只是bool 变量将转换。给定示例中的 bool 变量已被视为 true。 导致问题的原因是想象我想转换回转换后的值。这就是它抛出异常的地方,因为例如“w”字符不能转换为bool。但如果输出为01,则可以重新转换。

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 sample

【问题讨论】:

标签: c++ boost


【解决方案1】:

C++ 标准没有指定布尔值如何存储在内存中,只有两个可能的值:truefalse。现在,在您的机器上,我假设它们分别存储为10。允许编译器做出假设,特别是允许假设这些将是唯一存储在布尔值中的两个值。

因此,当boost::lexical_cast 看到布尔值时,它运行的代码可能看起来像这样(优化后)

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

如果value01,这可以正常工作并且可以满足您的需求。但是,您将71 放入其中。所以我们将'0'(48)的ASCII码加到71中,得到119,即'w'的ASCII码。

现在,我不是 C++ 标准专家,但我猜想用memcpy 将非标准值存储到布尔值中是未定义的行为。至少,您的代码是不可移植的。就这一点而言,也许更精通标准的人可以填补我的知识空白。

【讨论】:

  • 你是对的。不允许摆弄此类事物的内部部分。
  • C++11 used to say this explicitly,虽然我在最近的版本中找不到那个注释(但它仍然是真的)
  • 好吧,出于编辑原因,它已在 this edit 中删除(因此它将在 C++20 中消失,但脚注在 C++17 中仍然存在)。同样,基本事实仍然是正确的!
【解决方案2】:

你违反了规则。你期待什么,C++ 会在你的程序中添加无用的代码来捕获规则破坏者?

布尔变量只能是 0 或 1,false 或 true。他们,如果你按照规则正确地分配给他们。

如果你 memcpy 或者 reinterpret_cast 那么底层实现就会显示出来。 bool 是一个内存字节。如果它以某种方式设置为 0 或 1 以外的值,那么它就在那里。

我必须仔细检查,但我什至不确定你是否能保证 bool 一个字节。我认为您可以指向它。但如果硬件有办法创建指向一位的指针,您可能会对 C++ 的做法感到非常惊讶。

【讨论】:

  • "我必须仔细检查,但我什至不确定你是否保证 bool 是一个字节" sizeof(bool) 必须至少 1 . 它的大小与 int 相同是常见的。
  • @Bathsheba 当人们在奇怪的硬件上实现 C 或 C++ 时,他们必须做出妥协。在 RAM 有限且最小大小为 32 位“字节”的机器上,您是要浪费 31 位来存储 1 位,还是采取一些妥协?
  • 确实如此。我发表评论的目的是让您删除“我必须仔细检查”部分。
  • “布尔变量只能为0或1,假或真”。不,它们只能是假的或真的。时期。它们永远不可能是 0 或 1。它们不是数字。它们是布尔值。他们会很高兴地转换为 0 或1。很大的区别! (以及这个问题的症结所在)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
相关资源
最近更新 更多