2017-10-19 78 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的'而不是'+'促銷活動,其中更以讀取和寫入,但表達的意圖更好的(和將是那些不明白的推廣還沒有清晰的)。 –

相關問題