62

バイトのバッファは、signedcharまたはunsignedchar、あるいは単にcharバッファにする必要がありますか?CとC++の違いはありますか?

ありがとう。

4

14 に答える 14

50

任意のバイナリ データを保存する場合は、unsigned char. これは、C 標準によってパディング ビットがないことが保証されている唯一のデータ型です。他の各データ型には、オブジェクト表現 (値を決定するビットだけではなく、オブジェクトのすべてのビットを含むもの) にパディング ビットが含まれる場合があります。パディング ビットの状態は指定されておらず、値の格納には使用されません。したがって、charバイナリ データを使用して読み取ると、(値のビットのみを解釈することによって) char の値の範囲に切り詰められますが、無視されるだけで存在し、 によって読み取られるビットがまだ存在する可能性がありますmemcpy。実際の構造体オブジェクトのパディング ビットによく似ています。タイプunsigned charはそれらを含まないことが保証されています。それは5.2.4.2.1/2(C99 TC2、ここではn1124)から続きます:

型 char のオブジェクトの値が式で使用されるときに符号付き整数として扱われる場合、 の値は の値とCHAR_MIN同じでSCHAR_MINあり、 の値は の値とCHAR_MAX同じでなければなりませんSCHAR_MAX。それ以外の場合、 の値は CHAR_MIN0 であり、 の値は の値とCHAR_MAX同じです UCHAR_MAXUCHAR_MAXは等しくなければならない2^CHAR_BIT − 1

最後の文から、パディング ビット用のスペースが残っていないことがわかります。バッファの型としてを使用する場合char、オーバーフローの問題もあります。8ビットの範囲内にあるそのような要素に任意の値を明示的に割り当てます。 a char、これはCHAR_MIN..CHAR_MAXであり、このような変換はオーバーフローし、シグナルの発生を含む実装定義の結果を引き起こします。

上記に関する問題が実際の実装ではおそらく表示されない場合でも (実装の品質が非常に低くなる可能性があります)、最初から適切な型を使用することをお勧めしますunsigned char

ただし、文字列の場合、選択するデータ型は ですchar。これは、文字列関数と印刷関数によって理解されます。signed charこれらの目的で使用することは、私にとって間違った決定のように思えます。

詳細についてthis proposalは、C 標準の次のバージョンの修正が含まれているものをお読みください。最終的にはsigned charパディング ビットも不要になります。すでにワーキングペーパーに組み込まれています。

于 2009-03-17T11:53:46.650 に答える
39

バイトのバッファは、signed char か unsigned char か、単に char バッファか? C と C++ の違いはありますか?

言語がそれを処理する方法の小さな違い。慣習がそれをどのように扱うかの大きな違い。

  • char= ASCII (または UTF-8、ただし符号が邪魔になる)テキストデータ
  • unsigned char= バイト
  • signed char= めったに使用されない

そして、そのような区別に依存するコードがあります。ちょうど 1 週間か 2 週間前に、JPEG データが Base64 エンコード関数のバージョンに渡されたために破損するというバグに遭遇しました。これchar*は、「文字列」内の無効な UTF-8 をすべて「うまく」置き換えました。BYTE別名に変更するunsigned charだけで修正できました。

于 2011-02-20T15:46:53.617 に答える
12

場合によります。

charバッファがテキストを保持することを意図している場合、それを の配列として宣言し、それがデフォルトで署名されているか署名されていないかをプラットフォームに判断させることがおそらく理にかなっています。これにより、たとえば、実装のランタイム ライブラリとの間でデータをやり取りする際のトラブルを最小限に抑えることができます。

バッファーがバイナリ データを保持することを意図している場合は、使用方法によって異なります。たとえば、バイナリ データが実際には、符号付きの 8 ビット固定小数点 ADC 測定値であるデータ サンプルのパックされた配列である場合signed charが最適です。

ほとんどの実際のケースでは、バッファは単なるバッファであり、個々のバイトのタイプはあまり気にしません。これは、一括操作でバッファをいっぱいにして、それをパーサーを使用して複雑なデータ構造を解釈し、何か役に立つことを行います。その場合は、最も簡単な方法で宣言してください。

于 2009-03-17T08:03:26.253 に答える
9

マシンのデフォルトロケールの文字列ではなく、実際には8ビットバイトのバッファである場合は、を使用しますuint8_t。charがバイト(またはバイトがオクテット)ではないマシンがたくさんあるわけではありませんが、「これは文字列です」ではなく「これはオクテットのバッファです」というステートメントを作成すると、多くの場合、役立つドキュメントになります。

于 2009-03-17T09:49:02.770 に答える
5

charまたはunsigned charのいずれかを使用する必要がありますが、signed charは使用しないでください。規格は 3.9/2 で次のとおりです。

POD 型 T のオブジェクト (基本クラスのサブオブジェクト以外) の場合、オブジェクトが型 T の有効な値を保持しているかどうかにかかわらず、オブジェクトを構成する基になるバイト (1.7) を char または unsigned の配列にコピーできます。 char.char または unsigned char の配列の内容がオブジェクトにコピーされた場合、オブジェクトはその後元の値を保持します。

于 2009-03-17T11:08:26.260 に答える
3

最大限の移植性を得るには、常にunsignedcharを使用してください。これが関係する可能性のある例がいくつかあります。異なるエンディアンタイプのシステム間で共有されるシリアル化されたデータがすぐに思い浮かびます。シフトまたはビットマスキングを実行する場合、値は別です。

于 2009-03-17T10:05:31.967 に答える
3

unsigned char として定義した方がよいでしょう。実際、Win32 型の BYTE は unsigned char として定義されています。この間に C と C++ の違いはありません。

于 2009-03-17T08:01:18.877 に答える
2

int8_t と uint8_t の選択は、ptr を NULL と比較する場合と似ています。


機能の観点からは、NULL との比較は 0 との比較と同じです。NULL は 0 の #define であるためです。

しかし、個人的には、コーディングスタイルの観点から、私は自分のポインターを NULL と比較することを選択します。なぜなら、NULL #define は、コードを保守している人に、あなたが悪いポインターをチェックしていることを暗示しているからです...

VS

誰かが 0 との比較を見た場合、それはあなたが特定の値をチェックしていることを意味します。


上記の理由から、uint8_t を使用します。

于 2009-03-17T14:44:36.193 に答える
0

要素をより広い変数にフェッチすると、もちろん符号拡張されるかどうかになります。

于 2009-03-17T07:55:25.617 に答える
0

データのバイナリ性を強調したい場合は、より「生」のように感じられ、「ねえ、それはただの小さな集まりだ」と言うのはあまり魅力的ではないので、私は unsigned を好む傾向があります。ints

signed charバイトのバッファを表すために明示的に使用したことはないと思います。

もちろん、3 番目の選択肢の 1 つは、バッファーをできるだけ表現するvoid *ことです。多くの一般的な I/O 関数は で動作するvoid *ため、使用する整数型の決定を完全にカプセル化できる場合があります。これは便利です。

于 2009-03-17T08:01:02.980 に答える
0

数年前、128 を超える ASCII 値に対して色付きの文字を出力する C++ コンソール アプリケーションで問題が発生しました。これは、char から unsigned char に切り替えることで解決されましたが、char 型を維持しながらも解決できたと思います。

今のところ、ほとんどの C/C++ 関数は char を使用しており、両方の言語をよりよく理解できるようになったので、ほとんどの場合に char を使用しています。

于 2009-03-17T08:03:08.467 に答える
0

本当に気にする?そうでない場合は、デフォルト (char) をそのまま使用し、重要でない事項でコードを乱雑にしないでください。そうしないと、将来のメンテナーは、なぜ署名付き (または署名なし) を使用したのか不思議に思うでしょう。彼らの生活をよりシンプルにします。

于 2009-03-17T08:06:58.803 に答える
-1
typedef char byte;

byteこれで、配列をsにすることができます。意図したことは誰の目にも明らかであり、機能が失われることはありません。

少しばかげていることはわかっていますが、意図したとおりにコードを 100% 読み取ることができます。

于 2009-03-17T15:10:11.983 に答える
-1

コンパイラに嘘をつくと、罰せられます。

通過するだけのデータがバッファに含まれていて、それらを操作しない場合は問題ありません。

ただし、バッファの内容を操作する必要がある場合は、正しい型宣言によってコードが単純になります。「int val = buf[i] & 0xff;」なし ナンセンス。

そのため、データが実際に何であり、それをどのように使用する必要があるかを考えてください。

于 2009-03-17T14:57:30.437 に答える