2017-10-19 180 views
1

我(C++新手)我目前正在努力实现以下功能:C++:序列化字节数组十六进制字符串

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

使用此功能,outpu t是:

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 

我的问题是:

  • 为什么第二个版本和冷杉st不?这里的主要区别是什么?
  • 第二个版本是否正确执行我的初衷还是会出现其他问题吗?
+0

'+'什么都不做,但是做了你想要的东西,也就是确保字节被解释为正数 –

+0

请记住'char'类型可以是'signed' *或*'unsigned',它是up编辑器。在你的情况下,它们似乎是'signed',这意味着当字符[升级为'int'](http://en.cppreference.com/w/c/language/conversion#Integer_promotions)时,它们也是*符号扩展*。 –

+1

@PasserBy角色的一元'+'力[*整数升级*](http://en.cppreference.com/w/c/language/conversion#Integer_promotions)。 –

回答

1

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

char可以是signedunsigned,即至编译器的决定。由于你得到的输出,我们可以说,在你的情况下,char实际上是signed char

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

+0

谢谢你的答案!你对我的第二个问题也有评论吗? – bmk

+0

@bmk您的第二个解决方案可以正常工作,并且应该是可移植的。唯一的“改善”可能是一个明确的'的static_cast的'而不是'+'促销活动,其中更以读取和写入,但表达的意图更好的(和将是那些不明白的推广还没有清晰的)。 –

相关问题