C++標準ライブラリがbasic_ [io] streamとそのすべてのバリアントをunsigned char
型の代わりにchar
型を使用してインスタンス化した理由をいつも疑問に思っていました。 char
は、(署名されているかどうかに応じて)get()などの操作でオーバーフローとアンダーフローが発生する可能性があることを意味します。これにより、関連する変数の実装定義値が得られます。もう1つの例は、put
関数を使用して、フォーマットされていないバイトをostreamに出力する場合です。
何か案は?
注:私はまだ本当に確信していません。したがって、決定的な答えを知っている場合でも、実際に投稿することができます。
おそらく私は質問を誤解しましたが、unsigned charからcharへの変換は不特定ではなく、実装に依存します(C++標準では4.7-3)。
C++の1バイト文字のタイプは、「unsignedchar」ではなく「char」です。これにより、実装はプラットフォーム上で最善を尽くすための自由度が少し高まります(たとえば、標準化団体は、符号付きバイト演算が符号なしバイト演算よりも高速なCPUが存在すると信じていたかもしれませんが、それは私の推測です)。 Cとの互換性のためにも。C++からこの種の実存的な不確実性を取り除いた結果はC#です;-)
「char」型が存在することを考えると、その符号が定義されていなくても、通常のストリームがそれを使用することは理にかなっていると思います。したがって、おそらくあなたの質問は、「なぜC++はcharをunsignedとして定義しなかったのですか?」という答えによって答えられます。
私はいつもこのように理解してきました。iostream
クラスの目的は、文字のストリームを読み書きすることです。文字のストリームは、考えてみると、コンピュータによってのみ表される抽象的なエンティティです。文字エンコード。 C++標準では、「文字として宣言されたオブジェクト(char
)は、実装の基本文字セットのメンバーを格納するのに十分な大きさでなければならない」とだけ言って、文字エンコードの固定を避けるのに非常に苦労しています。 C++言語を定義するために「実装基本文字セット」を強制する必要があります。標準では、どの文字エンコードを使用するか(コンパイラとSTL実装)の決定を任せることができ、char
オブジェクトは、一部のエンコーディングで単一の文字を表します。
実装作成者は、 ISO-8859-1 などのシングルオクテットエンコーディング、または CS-2 などのダブルオクテットエンコーディングを選択できます。それは問題ではありません。 char
オブジェクトが「実装の基本文字セットのメンバーを格納するのに十分な大きさ」である限り(これは明示的に禁止されていることに注意してください 可変長エンコーディング )、実装は一般的なエンコーディングと互換性のない方法で基本的なラテン語を表すエンコーディングを選択してください!
char
、signed char
、およびunsigned char
タイプが名前で「char」を共有することは混乱を招きますが、char
は共有しないことに注意することが重要です。 signed char
およびunsigned char
と同じ基本タイプのファミリーに属しています。 signed char
は、符号付き整数型のファミリーに含まれます。
4つの符号付き整数型があります:「signedchar」、「short int」、「int」、および「longint」。
unsigned char
は、符号なし整数型のファミリーに含まれます。
符号付き整数型ごとに、対応する(ただし異なる)符号なし整数型が存在します: "unsigned char"、 "unsigned short int"、 " unsigned int」、および「unsigned long int」、.。
char
、signed char
、およびunsigned char
タイプの1つの類似点は、「[それらは]同じ量のストレージを占有し、同じ配置要件を持っている」ということです。したがって、実行文字セット内の文字の数値を判別するために、reinterpret_cast
からchar *
までunsigned char *
することができます。
あなたの質問に答えるために、STLがデフォルトタイプとしてchar
を使用する理由は、標準ストリームが整数ではなくchar
オブジェクトで表される文字のストリームの読み取りおよび/または書き込みを目的としているためです。 (signed char
およびunsigned char
)。数値に対してchar
を使用することは、関心の分離の方法です。
charは文字用、unsigned charはデータの生バイト用、signedcharは署名付きデータ用です。
標準では、charの実装にsignedまたはunsignedcharを使用するかどうかは指定されていません。コンパイラ固有です。これは、「char」がシステム上で文字を保持するのに「十分」であることを指定するだけです。つまり、当時の文字の状態、つまりUNICODEはありません。
文字に「char」を使用するのが標準的な方法です。 unsigned charの使用はハックですが、ほとんどのプラットフォームでのコンパイラのcharの実装と一致します。
this コメントがよく説明していると思います。引用するには:
符号付き文字と符号なし文字は、intやunsigned intと同じように、算術整数型です。一方、charは、プラットフォーム上の不透明なシステム固有の基本的なデータ単位を表す「I/O」タイプであることを明確に意図しています。私はこの精神でそれらを使用します。