std::vector<unsigned char>
インターネット上には、またはバイナリ データに類似したものを使用する必要があることを示唆する投稿がいくつかあります。
std::basic_string
しかし、多くの便利な文字列操作関数を提供するので、私はむしろそのバリアントを好みます。そして、私の知る限り、C++11以降、既知のすべてのC++03実装がすでに行っていること、つまりstd::basic_string
その内容をメモリに連続して保存することを標準が保証しています。
一見するstd::basic_string<unsigned char>
と、良い選択かもしれません。
std::basic_string<unsigned char>
ただし、ほとんどすべてのオペレーティング システム関数は のみを受け入れchar*
、明示的なキャストが必要になるため、 は使用したくありません。また、文字列リテラルはconst char*
であるため、文字列リテラルをバイナリ文字列に割り当てるたびに明示的なキャストが必要になりますがconst unsigned char*
、これも避けたいと思います。また、ファイルまたはネットワーク バッファから読み書きするための関数も同様char*
にconst char*
ポインタを受け入れます。
これstd::string
は基本的に の typedef である を残しますstd::basic_string<char>
。
std::string
バイナリデータをstd::string
使用することに関する唯一の潜在的な残りの問題 (私が見ることができる)は、 char
(署名できる) を使用することです。
char
、signed char
、およびunsigned char
は 3 つの異なるタイプでありchar
、符号なしまたは符号付きのいずれかです。
したがって、 の実際のバイト値がchar11111111b
から返されstd::string:operator[]
、その値を確認したい場合、その値は255
(char
符号なしの場合) または「負の値」 (char
数値表現に応じて符号付きの場合) のいずれかになります。 )。
11111111b
同様に、実際のバイト値をに明示的に追加したい場合、が署名されていてtoの会話がオーバーフローになる場合std::string
、単純に追加(char) (255)
することは処理系で定義されている可能性があります (シグナルを生成することさえあります) 。char
int
char
それで、これを回避する安全な方法はありstd::string
ますか?
§3.10/15 は次のように述べています。
プログラムが、次の型以外のglvalueを介してオブジェクトの格納された値にアクセスしようとした場合、動作は未定義です。
- [...]
- オブジェクトの動的な型に対応する符号付きまたは符号なしの型である型、
- [...]
- char または unsigned char 型。
私がそれを正しく理解していれば、unsigned char*
ポインターを使用して a の内容にアクセスして操作できるようにstd::string
なり、これも明確に定義されます。ビットパターンを として再解釈するだけunsigned char
で、変更や情報の損失はありません。後者は、char
、signed char
、およびのすべてのビットをunsigned char
値表現に使用する必要があるためです。
次に、このunsigned char*
内容の解釈を、std::string
その範囲内のバイト値にアクセスして変更する手段として、それ自体[0, 255]
の署名に関係なく、明確に定義された移植可能な方法で使用できchar
ます。
これにより、潜在的に署名された から生じる問題が解決されchar
ます。
私の仮定と結論は正しいですか?
また、unsigned char*
同じビット パターン (11111111b
または10101010b
) の解釈は、すべての実装で同じであることが保証されていますか? 別の言い方をすれば、標準は「目を通して見る」ことを保証していunsigned char
ますか?同じビットパターンは常に同じ数値につながります(バイトのビット数が同じであると仮定します)?
したがって、C++ 11 でバイナリ データを格納および操作するために安全に (つまり、未定義または実装定義の動作なしで) 使用できますか?std::string