バイトのバッファは符号付きまたは符号なしの文字バッファである必要がありますか?
質問
バイトのバッファは、signed char、unsigned char、または単にcharバッファですか? CとC ++の違いは何ですか?
ありがとう。
解決
バイトのバッファに署名する必要があります charまたはunsigned charまたは単にchar バッファ? Cとの違い C ++?
言語による処理方法のわずかな違い。慣例による処理方法の大きな違い。
-
char
= ASCII(またはUTF-8、ただし署名はそこにある)テキストデータ -
unsigned char
=バイト -
signed char
=めったに使用されない
そして、そのような区別に依存するコードがあります。 1〜2週間前に、BasePEGエンコード関数<!>#8212のchar*
バージョンに渡されたためにJPEGデータが破損するというバグに遭遇しました。 which <!> quot; helpfully <!> quot; <!> quot; string <!> quot;のすべての無効なUTF-8を置き換えました。 BYTE
aka <=>に変更するだけで修正できました。
他のヒント
任意のバイナリデータを保存する場合は、unsigned char
を使用する必要があります。 C標準によってパディングビットがないことが保証されている唯一のデータ型です。他の各データ型には、オブジェクト表現にパディングビットが含まれている場合があります(つまり、値を決定するビットのみではなく、オブジェクトのすべてのビットを含むビット)。パディングビットの状態は指定されておらず、値の保存には使用されません。したがって、char
いくつかのバイナリデータを使用して読み取ると、値のビットのみを解釈することにより、値はcharの値の範囲に削減されますが、無視されただけでまだ読み取られているビットがまだある可能性がありますmemcpy
。実際のstructオブジェクトのパディングビットによく似ています。タイプ5.2.4.2.1/2
にはこれらが含まれないことが保証されています。 CHAR_MIN
(C99 TC2、ここではn1124)から次のようになります。
char型のオブジェクトの値が、使用されるときに符号付き整数として扱われる場合 式では、
と等しくなりますSCHAR_MIN
の値はCHAR_MAX
の値と同じであり、SCHAR_MAX
の値はUCHAR_MAX
の値と同じです。それ以外の場合、値2^CHAR_BIT − 1
は0であり、8
の値はsigned char
。 値this proposal
は<=>
最後の文から、パディングビット用のスペースが残っていないことがわかります。バッファのタイプとして<=>を使用すると、オーバーフローの問題も発生します。<=>ビットの範囲内にあるそのような要素に値を明示的に割り当てる-そのような割り当てが正常であると予想される場合があります- <=>(<=> .. <=>)の範囲内ではありません。このような変換はオーバーフローし、シグナルの発生を含む実装定義の結果を引き起こします。
上記に関する問題が実際の実装ではおそらく表示されない場合でも(非常に実装の質が悪い)、最初から適切なタイプを使用するのが最善です。 <=>。
ただし、文字列の場合、選択するデータ型は<=>であり、文字列および印刷関数によって理解されます。これらの目的で<=>を使用することは、私にとって間違った決定のように見えます。
詳細については、 <=> をご覧ください。 a>次のバージョンのC標準の修正が含まれます。最終的には、<=>にはパディングビットも必要ありません。 ワーキングペーパーに既に組み込まれています。
状況によります。
バッファがテキストを保持することを目的としている場合、おそらくchar
の配列として宣言し、プラットフォームがデフォルトで署名されているか署名されていないかをプラットフォームに判断させることが理にかなっています。これにより、たとえば、実装のランタイムライブラリとの間でデータをやり取りする際のトラブルが最小限に抑えられます。
バッファがバイナリデータを保持することを目的としている場合、バッファの使用方法によって異なります。たとえば、バイナリデータが、8ビットの固定小数点ADC測定値に署名されたデータサンプルのパック配列である場合、signed char
が最適です。
ほとんどの実際のケースでは、バッファーは単なるバッファーであり、個々のバイトのタイプは実際には気にしません。なぜなら、バッファーを一括操作で埋めて、それを渡そうとしているからです。複雑なデータ構造を解釈し、何か便利なことをするためにパーサーに渡してください。その場合、最も簡単な方法で宣言してください。
マシンのデフォルトロケールの文字列ではなく、実際に8ビットバイトのバッファである場合、uint8_t
を使用します。 charがバイト(またはバイトがオクテット)でないマシンがたくさんあるわけではありませんが、「this is a string」ではなく「this is a buffer of octets」というステートメントを作成することは、多くの場合有用なドキュメントです。
char または unsigned char を使用する必要がありますが、 signed char は使用しないでください。この標準には3.9 / 2で次のものがあります
任意のオブジェクト(a PODタイプTのベースクラスサブオブジェクト)、 オブジェクトが保持するかどうか 型Tの有効な値、基になる オブジェクトを構成するバイト(1.7) charの配列にコピーされるか、 符号なし文字。 charまたはunsigned charの配列は オブジェクトにコピーバックされ、 オブジェクトはその後、 元の値。
unsigned charとして定義することをお勧めします。 Infact Win32型BYTEは、unsigned charとして定義されています。 C <!> ampに違いはありません。この間のC ++。
移植性を最大限に高めるには、常にunsigned charを使用してください。これが機能する可能性のあるインスタンスがいくつかあります。エンディアンの種類が異なるシステム間で共有されるシリアル化されたデータはすぐに思い浮かびます。シフトまたはビットマスキングを実行する場合、値は別です。
int8_tとuint8_tの選択は、ptrをNULLと比較する場合と似ています。
機能の観点から、NULLは0の#defineであるため、NULLとの比較は0との比較と同じです。
しかし、個人的には、コーディングスタイルの観点から、ポインターをNULLと比較することにしました。NULL#defineは、悪いポインターをチェックしているコードを保持している人を暗示するからです...
VS
0との比較が表示された場合、特定の値を確認していることを意味します。
上記の理由から、uint8_tを使用します。
要素をより広い変数にフェッチする場合、もちろん符号拡張されるかされません。
する必要があります...私は quot を無署名にする傾向があります。データのバイナリ性を強調したい場合は、小さなints
<!> quot;の束。
バイトのバッファを表すために明示的なsigned char
を使用したことはないと思います。
もちろん、3番目のオプションの1つは、バッファを可能な限りvoid *
として表現することです。多くの一般的なI / O関数は<=>で機能するため、使用する整数型の決定を完全にカプセル化できる場合があります。これは素晴らしいことです。
数年前に、128を超えるASCII値に対して色付きの文字を印刷するC ++コンソールアプリケーションで問題が発生しました。これは、charからunsigned charに切り替えることで解決しましたが、charタイプも維持しながら解決できたと思います。
今のところ、ほとんどのC / C ++関数はcharを使用していますが、今では両方の言語をよりよく理解しているため、ほとんどの場合charを使用しています。
本当に気にしますか?そうしない場合は、デフォルト(char)を使用するだけで、重要ではないコードでコードが乱雑にならないようにしてください。そうしないと、将来のメンテナーは、なぜ署名(または署名なし)を使用したのか疑問に思うでしょう。人生をもっとシンプルに。
コンパイラーに嘘をつくと、罰せられます。
バッファに単に通過するデータが含まれていて、それらを操作しない場合、それは重要ではありません。
ただし、バッファの内容を操作する必要がある場合は、正しい型宣言によりコードが簡単になります。 <!> quot; int val = buf [i] <!> amp; 0xff; <!> quot;ナンセンス。
つまり、データが実際に何であり、どのように使用する必要があるかを考えてください。
typedef char byte;
これで、配列をbyte
sにすることができます。あなたが意図したことは誰にでも明らかであり、機能を失うことはありません。
やや馬鹿げていることはわかっていますが、意図したとおりにコードが100%読み取られます。