web-dev-qa-db-ja.com

uint8_tとunsigned charの比較

Cでuint8_tよりunsigned charを使うことの利点は何ですか?

私は、ほとんどすべてのシステムでuint8_tunsigned charの単なるtypedefであることを知っています、それでなぜそれを使うのですか?

209
Lyndon White

それはあなたの意図を文書化しています - あなたは文字ではなく少数を格納するでしょう。

あなたがuint16_tint32_tのような他のtypedefを使っているならば、それはよりよく見えます。

204
Mark Ransom

念のために言うと、システムによっては8ビットタイプを持たないかもしれません。によると ウィキペディア

N = 8、16、32、または64の整数型を定義するための実装が必要とされる場合に限り、N = 8、16、32、または64が必要です。適切な型をサポートしていても、他のNに対して定義する必要はありません。

だからuint8_tは存在することを保証されていません、それは8ビット= 1バイトであるすべてのプラットフォームのためにそうするでしょうが。いくつかの組み込みプラットフォームは異なるかもしれませんが、それは非常にまれになっています。システムによってはchar型を16ビットに定義するかもしれません。その場合、8ビット型はおそらくないでしょう。

それ以外の(マイナーな)問題、 @ Mark Ransomの答え 私の意見では最高です。データを使用している目的を最も明確に示すものを使用してください。

また、uint8_tstdint.hヘッダーで提供されるC99の標準のtypedef)ではなくuint_8を意味していると思います。

63
Chris Lutz

要は、実装に依存しないコードを書くことです。 unsigned charは8ビット型であることが保証されていません。 uint8_tは(利用可能な場合)です。

40
AnT

私の経験では、uint8_tを8ビット(およびuint16_tなど)を意味するために使用したい場所と、8ビットより小さいフィールドを使用できる場所が2箇所あります。どちらの場所もスペースが重要な場所であり、デバッグ時にデータの生のダンプを見て、それが何を表しているのかを素早く判断できる必要があることがよくあります。

1つ目はRFプロトコル、特に狭帯域システムです。この環境では、できるだけ多くの情報を1つのメッセージにまとめる必要があるかもしれません。 2つ目はフラッシュストレージで、非常に限られたスペースしかありません(組み込みシステムなど)。どちらの場合も、圧縮されたデータ構造を使用することができます。この場合、コンパイラは圧縮と展開の処理を行います。

#pragma pack(1)
typedef struct {
  uint8_t    flag1:1;
  uint8_t    flag2:1;
  padding1   reserved:6;  /* not necessary but makes this struct more readable */
  uint32_t   sequence_no;
  uint8_t    data[8];
  uint32_t   crc32;
} s_mypacket __attribute__((packed));
#pragma pack()

どちらの方法を使用するかは、コンパイラによって異なります。同じヘッダファイルを持ついくつかの異なるコンパイラをサポートする必要があるかもしれません。これは、デバイスとサーバーが完全に異なる可能性がある組み込みシステムで発生します。たとえば、x86 Linuxサーバーと通信するARMデバイスがあるとします。

パック構造を使用する際の注意点がいくつかあります。最大の問題は、あなたがメンバーのアドレスを間接参照することを避けなければならないということです。マルチバイトでアラインされた単語を持つシステムでは、これはミスアラインの例外とコアダンプをもたらす可能性があります。

何人かの人々はまた性能について心配し、これらのパックされた構造を使用することはあなたのシステムを遅くすると主張するでしょう。舞台裏では、コンパイラは整列されていないデータメンバにアクセスするためのコードを追加します。 IDEのアセンブリコードを見ればわかります。

しかし、パック構造体は通信やデータ保存に最も有用であるため、データをメモリ内で使用するときには、データを非パック表現に抽出することができます。通常、メモリ内のデータパケット全体を処理する必要はありません。

ここでいくつかの関連議論があります:

プラグマpack(1)も__attribute__((aligned(1)))も動作します

gccの__attribute __((packed))/ #pragma packは危険ですか?

http://solidsmoke.blogspot.ca/2010/07/woes-of-structure-packing-pragma-pack.html

7
Tereus Scott

あなたが言ったように、 "ほぼあらゆるシステム"。

charはおそらく変更される可能性が低いものの1つですが、uint16_tとその仲間を使い始めると、uint8_tを使用する方がうまく融合し、コーディング標準の一部になることさえあります。

7
Justin Love

ほとんどありません。移植性の観点から、charを8ビットより小さくすることはできず、charより小さくすることはできません。したがって、Cの実装に符号なし8ビット整数型がある場合、それはcharになります。あるいは、まったく持っていないかもしれません。その時点では、どのtypedefのトリックも議論の余地がありません。

それはあなたがそこに8ビットのバイトを必要とし、他には何も必要としないことが明らかであるという意味であなたのコードをより良く文書化するために使用されるかもしれません。しかし実際にはそれは事実上どこにでもすでに妥当な予想です(それが真実ではないDSPプラットフォームがありますが、そこでコードが実行される可能性はわずかであり、そしてプログラムの先頭で静的アサーションを使用してエラーアウトすることもできます)そのようなプラットフォーム)。

6
Pavel Minaev

あなたがネットワークアナライザを書いているとき、それは例えば本当に重要です。パケットヘッダは、特定のプラットフォームのCコンパイラの動作方法ではなく、プロトコル仕様によって定義されています。

3
VP.

ほとんどすべてのシステムで私はuint8_t == unsigned charを満たしていますが、これはC標準では保証されていません。あなたが移植可能なコードを書き込もうとしていて、それがメモリがどんなサイズであるか厳密に重要であるならば、uint8_tを使用してください。それ以外の場合は、unsigned charを使用してください。

2
atlpeg