web-dev-qa-db-ja.com

uint8_t、uint_fast8_t、uint_least8_tの違い

C99標準では、次のデータ型が導入されています。 AVR stdintライブラリのドキュメントは here にあります。

  • uint8_tは、8ビットの符号なし型であることを意味します。
  • uint_fast8_tは、8ビット以上の最速の符号なし整数であることを意味します。
  • uint_least8_tは、少なくとも8ビットの符号なし整数であることを意味します。

わかります uint8_tとは何ですかuint_fast8_t(レジスタレベルでどのように実装されているのかわかりません)。

1.「それはunsigned int少なくとも8ビット」

2.How uint_fast8_tおよびuint_least8_tは、uint8_t

69
mic

_uint_least8_t_は、少なくとも8ビットを持つ最小の型です。 _uint_fast8_t_は、少なくとも8ビットを持つ最速の型です。

エキゾチックなアーキテクチャを想像することで違いを見ることができます。 20ビットアーキテクチャを想像してください。 _unsigned int_には20ビット(1つのレジスタ)があり、_unsigned char_には10ビットがあります。したがって、sizeof(int) == 2ですが、char型を使用するには、レジスタを半分にカットするための追加の命令が必要です。次に:

  • _uint8_t_:は未定義です(8ビット型はありません)。
  • _uint_least8_t_:は_unsigned char_であり、8ビット以上の最小の型です。
  • _uint_fast8_t_:は_unsigned int_です。これは、私の想像上のアーキテクチャでは、ハーフレジスタ変数がフルレジスタ変数よりも遅いためです。
83
rodrigo

理論は次のようになります。

uint8_tは正確に8ビットである必要がありますが、存在する必要はありません。したがって、8ビット整数のモジュロ256割り当て動作*に依存している場合、および不明瞭なアーキテクチャでコンパイル動作が誤動作することを好む場合に使用する必要があります。

uint_least8_tは、少なくとも8ビットを格納できる、利用可能な最小の符号なし整数型である必要があります。大きな配列のようなもののメモリ使用を最小限に抑えたい場合に使用します。

uint_fast8_tは、少なくとも8ビットを格納できる「最速」の符号なし型であると想定されています。ただし、実際には、特定のプロセッサでの特定の操作で最速であることは保証されていません。値に対して多くの操作を実行するコードの処理で使用します。

実際には、「高速」タイプと「最小」タイプはあまり使用されません。

「最も少ない」タイプは、ほとんどの人がそうではないCHAR_BIT!= 8でアーキテクチャを不明瞭にする移植性に関心がある場合にのみ、本当に役立ちます。

「高速」タイプの問題は、「最速」の特定が難しいことです。タイプが小さいほど、メモリ/キャッシュシステムへの負荷が少なくなる可能性がありますが、ネイティブよりも小さいタイプを使用すると、追加の命令が必要になる場合があります。さらに、どちらが最適かはアーキテクチャのバージョン間で変わる可能性がありますが、実装者はそのような場合にABIを壊さないようにしたいことがよくあります。

人気のある実装を見ると、uint_fastn_tの定義はかなりfairly意的であるようです。 glibcは、多くの最新のプロセッサ(特に64ビットプロセッサ)がネイティブWordよりも小さいアイテムの高速操作をサポートしているという事実を考慮せずに、少なくとも問題のシステムの「ネイティブWordサイズ」として定義しているようです。サイズ。 IOSは明らかにそれらを固定サイズ型と同等であると定義しています。他のプラットフォームは異なる場合があります。

全体として、小さな整数を使用したタイトなコードのパフォーマンスが目標である場合は、さまざまなサイズのタイプで気になるプラットフォームでyourコードをベンチマークして、何が最適かを確認する必要があります。

*残念ながら、モジュロ256の割り当て動作は、Cの整数プロモーションの誤機能のおかげで、常にモジュロ256算術を意味するわけではないことに注意してください。

24
plugwash

uint8_t意味:正確に8ビットの符号なし整数を与えてください。

uint_least8_t意味:少なくとも8ビットの最小型の符号なし整数を教えてください。メモリ消費を最適化します。

uint_fast8_tは、少なくとも8ビットの符号なしintを提供します。アライメントを考慮して、プログラムを高速化する場合は、より大きなタイプを選択してください。速度を最適化します。

また、単純なint型とは異なり、上記のstdint.h型の署名付きバージョンは2の補数形式であることが保証されています。

23
Lundin

一部のプロセッサは、大きなデータタイプほど小さなデータタイプで効率的に動作できません。たとえば、次の場合:

uint32_t foo(uint32_t x, uint8_t y)
{
  x+=y;
  y+=2;
  x+=y;
  y+=4;
  x+=y;
  y+=6;
  x+=y;
  return x;
}

yuint32_t ARM Cortex-M3は単純に生成できます

add r0,r0,r1,asl #2   ; x+=(y<<2)
add r0,r0,#12         ; x+=12
bx  lr                ; return x

ただし、yuint8_tコンパイラは代わりに以下を生成する必要があります。

add r0,r0,r1          ; x+=y
add r1,r1,#2          ; Compute y+2
and r1,r1,#255        ; y=(y+2) & 255
add r0,r0,r1          ; x+=y
add r1,r1,#4          ; Compute y+4
and r1,r1,#255        ; y=(y+4) & 255
add r0,r0,r1          ; x+=y
add r1,r1,#6          ; Compute y+6
and r1,r1,#255        ; y=(y+6) & 255
add r0,r0,r1          ; x+=y
bx  lr                ; return x

「高速」型の意図した目的は、コンパイラーが、効率的に処理できない小さな型をより高速な型に置き換えることを可能にすることでした。残念ながら、「高速」タイプのセマンティクスはかなり不十分に指定されており、これにより、式が符号付きまたは符号なしの数学を使用して評価されるかどうかという疑問が残ります。

5
supercat

1.「少なくとも8ビットの符号なし整数」の意味を説明できますか?

それは明らかなはずです。符号なし整数型であり、幅が少なくとも8ビットであることを意味します。実際には、これは、少なくとも0〜255の数値を保持でき、負の数値を保持できないことを意味しますが、255を超える数値を保持できる場合があります。

0から255の範囲外の数値を保存する予定がある場合(および移植可能にする場合)、これらのタイプを使用しないでください。

2. uint_fast8_tとuint_least8_tは、uint8_tと比較して効率/コードスペースをどのように向上させるのですか?

uint_fast8_tはより高速である必要があるため、コードが高速であることが要件である場合はそれを使用する必要があります。一方、uint_least8_tでは、より小さいサイズの候補がないことが必要です。したがって、サイズが問題になる場合は、それを使用します。


そしてもちろん、厳密に8ビットにする必要がある場合は、uint8_tのみを使用します。 uint8_tを使用すると、uint8_tが存在する必要がないため、コードが移植不能になる場合があります(特定のプラットフォームにはそのような小さな整数型が存在しないため)。

4
skyking

「高速」整数型は、少なくとも必要なビット量で利用可能な最速の整数であると定義されています(あなたの場合は8)。

プラットフォームはuint_fast8_t なので uint8_tその後、速度にまったく違いはありません。

その理由は、ネイティブのWordの長さを使用していない場合に遅いプラットフォームがあるためです。

3
LPs