2017-10-19 17 views
1

I(C++初心者)は、現在、以下の機能を実装しようとしています:C++:16進文字列にバイト配列をシリアライズ

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 

私の質問は:

  • なぜ2番目のバージョンが動作し、 stはありませんか?ここでの主な違いは何ですか?
  • 2番目のバージョンは私のオリジナルの意図を正しく実装しているのですか、それとも他の問題がありますか?
+0

は '+'すなわち、しかし、あなたが望んでいたキャスト、何もしません、それは最高だ、 'char'タイプは' signed' *または* 'unsigned'のいずれかになりますことを覚えておいてください –

+0

バイトは正の数として解釈されていることを確認しました彼はコンパイラです。あなたのケースでは、それらは文字が[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)は2進数で左に埋められます(つまり、0xde0xffffffdeになります)。また、前述

charsignedまたはunsigned、コンパイラに任されて意思決定のいずれかであることができるということです。出力のために、私たちはあなたのケースではcharが実際にはsigned charであると言うことができます。

あなたが見つけた単純な解決策は、最初に文字をunsigned charにキャストし、次に(単項の+を使用して)intに昇格させることです。

+0

答えていただきありがとうございます!私の2番目の質問にもコメントしていますか? – bmk

+0

@bmk 2番目のソリューションは正常に動作し、移植可能でなければなりません。唯一の "改善"は、より多くの読み書きが可能ですが、より良い意図を表しています(まだ宣伝を理解していない人にとってはより明確になる)、 '+'プロモーションの代わりに明示的な 'static_cast 'でしょう。 –

関連する問題