uint8_tとunsigned char


231

使用することの利点は何であるuint8_t以上unsigned charCには?

ほとんどすべてのシステムuint8_tでのtypedefにすぎないことを知っているunsigned charので、なぜそれを使用するのですか?

回答:


225

それはあなたの意図を文書化します-あなたは文字ではなく小さな数字を保存します。

次のような他のtypedef使用している場合も、それはよりよいに見えるuint16_tかをint32_t


1
元の質問では、標準型について話しているのかどうかが明確ではありませんでした。長年にわたって、この命名規則には多くのバリエーションがあると思います。
Mark Ransom

8
装飾されていないことがキャラクターを操作していることを示しているので、意図を明示的に使用unsigned charまたはsigned char文書化しcharます。
caf

9
私は装飾unsignedunsigned intれていないのは当然のことだと思いましたか?
Mark Ransom

5
@endolith、文字列にuint8_tを使用することは必ずしも間違っているとは限りませんが、それは間違いなく奇妙です。
Mark Ransom

5
@endolith、私はUTF8テキストでuint8_tのケースを作ることができると思います。実際、charは文字を意味するようですが、UTF8文字列のコンテキストでは、マルチバイト文字の1バイトにすぎない場合があります。uint8_tを使用すると、すべての位置で文字を期待すべきでないことを明確にすることができます。つまり、文字列/配列の各要素は、意味論的な仮定を行うべきではない任意の整数です。もちろん、すべてのCプログラマはこれを知っていますが、初心者は正しい質問をするように強いられるかもしれません。
2014年

70

見やすくするために、一部のシステムには8ビットタイプがない場合があります。ウィキペディアによると:

N = 8、16、32、または64の正確な幅の整数型を定義するには、要件を満たす型がある場合にのみ、実装が必要です。適切なタイプをサポートしていても、他のNに対してそれらを定義する必要はありません。

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

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

また、私はあなたがuint8_t(標準に含まれていないstdint.h)というよりもuint_8(ヘッダーに提供されているC99からの標準のtypedef)を意味していると仮定しています


3
@caf、まったくの好奇心から-いくつかの説明にリンクできますか?C / C ++型の保証が弱すぎるかどうかに関するcomp.lang.c ++。moderatedディスカッションで誰かが言及した(そしてその開発者のドキュメントにリンクした)ため、それらが存在することはわかっていますが、そのスレッドを見つけることができず、常に便利です同様の議論でそれを参照するには:)
Pavel Minaev 2009年

3
「システムによっては、char型を16ビットと定義している場合があります。その場合、8ビット型は存在しません。」-そして、私からのいくつかの誤った異議にもかかわらず、Pavelは彼の回答で、charが16ビットの場合、コンパイラが8ビット型を提供しても、それを呼び出さない(またはtypedefでそれを呼び出さないuint8_t)ことを示しました。これは、8ビットタイプのストレージ表現に未使用のビットが含まれてuint8_tいるためです。
スティーブジェソップ

3
SHARCアーキテクチャには32ビットワードがあります。詳細については、en.wikipedia.org / wiki /…を参照してください。
BCran 2009年

2
また、TIのC5000 DSP(OMAP1およびOMAP2に含まれていた)は16ビットです。OMAP3では、8ビット文字のC6000シリーズに移行したと思います。
スティーブジェソップ

4
N3242を掘り下げる-「ワーキングドラフト、プログラミング言語C ++の標準」セクション18.4.1 <cstdint>の概要- typedef unsigned integer type uint8_t; // optional つまり、本質的に、C ++標準準拠ライブラリはuint8_tを定義するためにまったく必要ありません(コメント// optionalを参照) )
ナイトトレイル

43

重要なのは、実装に依存しないコードを記述することです。unsigned char8ビット型であるとは限りません。uint8_tあります(利用可能な場合)。


4
...それがシステムに存在する場合、それは非常にまれです。+1
クリス・ルッツ

2
uint8_tが存在しないためにシステムでコンパイルできないコードで本当に問題が発生した場合は、findとsedを使用して、uint8_tのすべての発生をunsigned charまたはより便利なものに自動的に変更できます。
バズ2014

2
@bazz-それができない8ビットタイプであると想定していない場合-たとえば、リモートシステムによってバイト単位でパッケージ化されたデータをアンパックする場合。暗黙的な仮定は、uint8_tが存在しない理由は、charが8ビットを超えるプロセッサ上にあるということです。
Chris Stratton

アサーションを投入assert(sizeof(unsigned char)== 8);
バズ2015

3
@bazz不正なアサーションです。1バイトsizeof(unsigned char)戻り1ます。ただし、システムのcharとintが同じサイズ(たとえば、16ビット)の場合sizeof(int)も返されます1
Toby

7

あなたが言ったように、「ほとんどすべてのシステム」。

charおそらく変更される可能性が低いものの1つですがuint16_t、使い始めたら、uint8_tブレンドをより適切に使用し、コーディング標準の一部となることもあります。


7

私の経験では、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


6

少ししかありません。移植性の観点からは、char8ビットより小さくすることはできず、それより小さくすることはできませんchar。そのため、特定のC実装に符号なし8ビット整数型がある場合、それはになりますchar。または、1つもまったくない場合があり、その時点ではtypedefトリックは無効です。

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


7
@Skizz-いいえ、標準ではunsigned char0から255までの値を保持できる必要があります。4ビットでそれを実行できる場合、私には不便です。
Chris Lutz、

1
「もう少し面倒だろう」-コンパイラの作成者がいた場所までずっと歩いて(泳いだり、飛行機を捕まえたり)、頭の後ろで平手打ちする必要があるという意味で面倒です。 、それらをuint8_t実装に追加します。16ビット文字を使用したDSP用のコンパイラーはuint8_t、通常、を実装するのか、しないのか。
スティーブジェソップ

6
-ところで、考え直しに、それはおそらく、「私は本当に8ビット必要がある」と言うための最も簡単な方法で#include <stdint.h>、かつ使用することをuint8_t。プラットフォームにそれがある場合、それはあなたにそれを与えます。プラットフォームにない場合、プログラムはコンパイルされず、理由は明確で簡単です。
Pavel Minaev 2009年

2
それでも葉巻はありません。申し訳ありません。「unsigned char以外の符号なし整数型の場合、オブジェクト表現のビットは、値ビットとパディングビットの2つのグループに分けられます...値ビットがNの場合、各ビットは異なるものを表す必要があります。 1と2 ^(N-1)の間の2のべき乗。その型のオブジェクトは、純粋なバイナリ表現を使用して0から2 ^(N-1)までの値を表すことができます... typedef名intN_tは、幅N、パディングビットなし、2の補数表現の符号付き整数型。」
Pavel Minaev 2009年

1
算術モジュロだけが必要な場合は、符号なしビットフィールドでも問題ありません(不便な場合)。たとえば、パディングのないオクテットの配列が必要なとき、つまり、SOLのときです。この話の
教訓は

4

これは、たとえばネットワークアナライザーを作成する場合に非常に重要です。パケットヘッダーは、特定のプラットフォームのCコンパイラの動作方法ではなく、プロトコル仕様によって定義されます。


私がこれを尋ねたとき、私はシリアル上のコミュニケーションのための簡単なプロトコルを定義していました。
リンドンホワイト

2

ほとんどすべてのシステムでuint8_t == unsigned charに出会いましたが、これはC標準では保証されていません。ポータブルコードを記述しようとしていて、メモリのサイズが正確に重要な場合は、uint8_tを使用します。それ以外の場合は、unsigned charを使用します。


3
uint8_t が8ビットのunsigned char場合、常に範囲とサイズ、およびパディング(なし)に一致しますunsigned char。ときはunsigned char8ビットではなく、uint8_t存在しません。
chux-モニカを2016年

@chux、それが言っている規格の正確な場所への参照がありますか?unsigned charが8ビットの場合uint8_ttypedefそのでありtypedef拡張された符号なし整数型ではないことが保証されますか?
hsivonen

@hsivonen "それがそれを言う標準の正確な場所?" ->いいえ-7.20.1.1をご覧ください。unsigned char/signed char/char8ビット以上の最小タイプと同様に、簡単に推測できます。 unsigned charパディングはありません。ためuint8_tであること、それは8ビット、パディングなしでなければならない、なぜなら実装設け整数型で存在する:最小限の要件に合致しますunsigned char。"... typedefであることが保証されている..."については、投稿するのに適した質問のようです。
chux-モニカを復活させる'28年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.