C ++:将字节数组序列化为十六进制字符串

时间:2017-10-19 07:00:43

标签: c++

I(C ++ newbie)我正在尝试实现以下功能:

std::string bytes_to_hex(const std::string &bytes);

该函数基本上应该返回给定字节数组的base16编码:

std::string input{0xde, 0xad, 0xbe, 0xef} => "deadbeef"

我的第一个版本并不像我想象的那样完成:

std::string bytes_to_hex(const std::string &bytes) {
    std::ostringstream ss;
    ss << std::hex;

    for (auto &c : bytes) {
        ss << std::setfill('0') << std::setw(2) << +c;
    }

    return ss.str();
}

使用此功能输出为:

ffffffdeffffffadffffffbeffffffef

经过一些实验,我发现这个版本看起来更好:

std::string bytes_to_hex(const std::string &bytes) {
    std::ostringstream ss;
    ss << std::hex;

    for (const char &c : bytes) {
        ss << std::setfill('0') << std::setw(2) << +(static_cast<uint8_t>(c));
    }

    return ss.str();
}

输出符合预期:

deadbeef

我的问题是:

  • 为什么第二个版本有效,第一个版本没有?这里的主要区别是什么?
  • 第二个版本是否正确实现了我的初衷还是会出现其他问题吗?

1 个答案:

答案 0 :(得分:1)

正如我的评论所述,一元+部队integer promotion。当发生这种情况时,签名类型是符号扩展,对于two's complement编码的整数,这意味着负数(最左边的位是1)用二进制数填充(即0xde变为0xffffffde)。

还提到char可以是signed unsigned,这是由编译器决定的。由于您得到了输出,我们可以说char实际上是signed char

您发现的简单解决方案是首先将角色投放到unsigned char,然后(使用一元+)将其提升为int