私の理解でint
は、当初は「ネイティブ」整数型であると想定されていましたが、サイズが少なくとも16ビットであることが保証されていました。当時は「妥当な」サイズと見なされていました。
32ビットプラットフォームが一般的になると、「合理的な」サイズが32ビットに変更されたと言えます。
- 最新のWindowsは
int
、すべてのプラットフォームで32ビットを使用します。
- POSIX
int
は、少なくとも32ビットであることを保証します。
- C#、Javaには、
int
正確に32ビットであることが保証されている型があります。
しかし、64ビットプラットフォームが標準になったとき、int
次の理由で64ビット整数に拡張された人は誰もいませんでした。
- 移植性:多くのコードは
int
、サイズが32ビットであることに依存しています。
- メモリ消費量:
int
ほとんどの場合、使用されている数は20億よりはるかに少ないため、すべてのメモリ使用量を2倍にすることはほとんどの場合不合理かもしれません。
さて、なぜあなたが好むだろうuint32_t
にuint_fast32_t
?同じ理由で、C#とJavaは常に固定サイズの整数を使用します。プログラマーは、さまざまなタイプの可能なサイズを考慮してコードを記述せず、1つのプラットフォーム用に記述し、そのプラットフォームでコードをテストします。ほとんどのコードは、データ型の特定のサイズに暗黙的に依存しています。そして、これがuint32_t
ほとんどの場合に良い選択である理由です-それはその振る舞いに関して曖昧さを許しません。
さらに、uint_fast32_t
32ビット以上のサイズのプラットフォームで本当に最速のタイプですか?あんまり。Windows上のx86_64用のGCCによるこのコードコンパイラを検討してください。
extern uint64_t get(void);
uint64_t sum(uint64_t value)
{
return value + get();
}
生成されたアセンブリは次のようになります。
push
sub $0x20,
mov
callq d <sum+0xd>
add
add $0x20,
pop
retq
ここで、get()
の戻り値をuint_fast32_t
(Windows x86_64では4バイト)に変更すると、次のようになります。
push %rbx
sub $0x20,%rsp
mov %rcx,%rbx
callq d <sum+0xd>
mov %eax,%eax ; <-- additional instruction
add %rbx,%rax
add $0x20,%rsp
pop %rbx
retq
mov %eax,%eax
32ビット値を64ビット値に拡張することを目的とした関数呼び出し後の追加の命令を除いて、生成されたコードがほぼ同じであることに注意してください。
32ビット値のみを使用する場合はそのような問題はありませんが、おそらくsize_t
変数付きの値(おそらく配列サイズ?)を使用し、x86_64では64ビットです。Linuxではuint_fast32_t
8バイトなので、状況は異なります。
多くのプログラマーはint
、小さな値を返す必要があるときに使用します(たとえば、[-32,32]の範囲)。これはint
、プラットフォームのネイティブ整数サイズの場合は完全に機能しますが、64ビットプラットフォームではないため、プラットフォームのネイティブタイプと一致する別のタイプの方が適しています(小さいサイズの他の整数で頻繁に使用される場合を除く)。
基本的に、標準が何を言っているかに関係なく、uint_fast32_t
とにかくいくつかの実装では壊れています。一部の場所で生成される追加の命令が気になる場合は、独自の「ネイティブ」整数型を定義する必要があります。またはsize_t
、通常はnative
サイズと一致するため、この目的で使用できます(8086のような古くてあいまいなプラットフォームは含まれていません。Windows、Linuxなどを実行できるプラットフォームのみが含まれています)。
int
ネイティブ整数型であると想定されていたことを示すもう1つの記号は、「整数昇格規則」です。ほとんどのCPUはネイティブでのみ操作を実行できるため、32ビットCPUは通常、32ビットの加算、減算などしか実行できません(Intel CPUはここでは例外です)。他のサイズの整数型は、ロードおよびストア命令によってのみサポートされます。たとえば、8ビット値は適切な「8ビット符号付きロード」または「8ビット符号なしロード」命令でロードする必要があり、ロード後に値を32ビットに拡張します。整数昇格規則がないと、Cコンパイラーは、ネイティブ型よりも小さい型を使用する式用にもう少しコードを追加する必要があります。残念ながら、これは64ビットアーキテクチャではもはや当てはまりません。コンパイラが場合によっては追加の命令を発行する必要があるためです(上記のとおり)。