web-dev-qa-db-ja.com

「int」と「int_fast16_t」の違いは何ですか?

私が理解しているように、C仕様では、型intは、少なくとも16ビットを含むターゲットプラットフォームで最も効率的な型であると想定されています。

C99のint_fast16_tの定義もそうではありませんか。

他のint_fastXX_tが必要なため、一貫性を保つために配置したのでしょうか?

更新

以下の議論を要約すると:

  • 私の質問は多くの点で間違っていました。 C標準ではintのビット数を指定していません。含める必要がある範囲[-32767,32767]を指定します。
  • 最初はほとんどの人が「しかし、その範囲は少なくとも16ビットを意味します!」しかし、Cは整数の2の補数(またはバイナリ)のストレージを必要としません。彼らが「16ビット」と言っていた場合、1ビットのパリティ、1ビットの符号、および14ビットのマグニチュードを持ち、「標準に適合」しているが、その範囲を満たさないプラットフォームがあるかもしれません。
  • 標準はintが最も効率的な型であることについて何も述べていません。上記のサイズ要件の他に、intは、コンパイラ開発者が最も重要と考える基準に基づいて決定できます。 (速度、サイズ、下位互換性など)
  • 一方、int_fast16_tは、おそらく他のトレードオフを犠牲にして、パフォーマンスに最適なタイプを使用する必要があるというヒントをコンパイラに提供するようなものです。
  • 同様に、int_least16_tは、遅くなる場合でも、16ビット以上の最小の型を使用するようコンパイラーに指示します。大規模な配列などでスペースを確保するのに適しています。

例: x86-64上のMSVCには、64ビットシステムであっても32ビットintがあります。 intは常に正確に32ビットであると想定している人が多すぎるため、MSはこれを選択しました。ただし、x86-64で64ビット値の方が高速である場合、int_fast32_tが64ビット数になる可能性があります。 (私は実際にはそうではないと思いますが、それは要点を示すだけです)

38

int_fast16_tは、16ビット以上のサイズで最速のintであることが保証されています。 intは、次の場合を除いて、そのサイズを保証しません。

 sizeof(char) = 1 and sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long).

そして、それは-32767から+32767の範囲を保持できます。

(7.20.1.3p2) "typedef名int_fastN_tは、少なくとも[〜#〜] n [〜#〜]の幅を持つ最速の符号付き整数型を示します。 typedef名uint_fastN_tは、少なくとも幅が[〜#〜] n [〜#〜]の最も高速な符号なし整数型を示します。 "

24
NathanOliver

intは、速度/サイズが「最も効率的なタイプ」ですが、C仕様では指定されていません。 16ビット以上である必要があります。

int_fast16_t少なくとも 16ビット整数の範囲で速度が最も効率的なタイプです。

例:特定のプラットフォームでは、速度だけでなく、さまざまな理由でintを32ビットにする必要があると判断した可能性があります。同じシステムが、16ビット整数の場合、異なるタイプが最も高速であると判断する場合があります。

例:64ビットマシンで、intを64ビットとして使用すると予想される場合、コンパイラーは互換性のために32ビットintコンパイルのモードを使用できます。このモードでは、int_fast16_tは本来64ビットである可能性があります。これはネイティブで最速の幅であるため、アライメントの問題などを回避するためです。

私が理解しているように、C仕様では、型intは、少なくとも16ビットを含むターゲットプラットフォームで最も効率的な型であると想定されています。

標準がintについて実際に言っているのは次のとおりです:( N1570ドラフト 、セクション6.2.5、パラグラフ5):

「プレーン」intオブジェクトは、実行環境のアーキテクチャによって提案された自然なサイズです(範囲INT_MININT_MAX定義どおりヘッダー内<limits.h>)。

INT_MINおよびINT_MAXへの参照は、おそらく少し誤解を招く可能性があります。これらの値は、タイプintの特性に基づいて選択され、逆ではありません。

また、「the自然なサイズ」というフレーズも少し誤解を招きやすいものです。ターゲットアーキテクチャによっては、整数型の「自然な」サイズが1つだけではない場合があります。

他の場所では、規格は、INT_MINは最大-32767である必要があり、INT_MAXは少なくとも+32767である必要があるとしています。これは、intが少なくとも16であることを意味しますビット。

これは、規格がint_fast16_t(7.20.1.3)について述べていることです。

次の各型は、少なくとも指定された幅を持つすべての整数型の中で通常最も高速に動作する整数型を指定します。

脚注付き:

指定されたタイプがすべての目的で最速であるとは限りません。あるタイプを別のタイプから選択する明確な根拠がない場合は、符号付きと幅の要件を満たす整数タイプを選択するだけです。

intint_fast16_tの要件は似ていますが、同一ではありません-どちらも同様にあいまいです。

実際には、intのサイズは、「自然なサイズ」以外の基準に基づいて選択されることが多く、またはその句は便宜上解釈されます。多くの場合、新しいアーキテクチャのintのサイズは、既存のアーキテクチャのサイズと一致するように選択され、コードの移植の難しさを最小限に抑えます。そして、intを32ビットより広くしないようにするかなり強い動機があるので、charshort、およびintは8のサイズをカバーできます。 、16、および32ビット。 64ビットシステム、特にx86-64では、「自然な」サイズはおそらく64ビットですが、ほとんどのCコンパイラはintを64ではなく32ビットにします(一部のコンパイラはlong 32ビット)。

int_fast16_tの基礎となる型の選択は、それを使用するすべてのコードが高速の16ビット符号付き整数型を明示的に要求しているため、このような考慮事項への依存度が低いと思います。既存のコードの多くは、標準で保証されている以上のintの特性を前提としているため、コンパイラーの開発者は、コンパイラーを使用する場合にそのようなコードに対応する必要があります。

7
Keith Thompson

C99の根拠7.8整数型のフォーマット変換<inttypes.h>(標準に付属するドキュメント)から、次の点を強調します。

C89は、言語が4つの符号付きおよび符号なし整数データ型、charshortintおよびlongをサポートする必要があることを指定していますが、それらの要件はほとんどありません。サイズそれ以外はintshortは少なくとも16ビットであり、longintと同じ長さで32以上であるビット。 16ビットシステムの場合、ほとんどの実装では、8、16、16、32ビットをそれぞれcharshortintlongに割り当てます。 32ビットシステムでは、8、16、32、32ビットをこれらのタイプに割り当てるのが一般的です。 intサイズのこの違いは、システムから別のシステムに移行して整数型に異なるサイズを割り当てるユーザーにいくつかの問題を引き起こす可能性があります。これは、Standard Cの整数昇格規則が予期せずサイレント変更を生成する可能性があるためです。 64ビットシステムの導入に伴い、拡張整数型を定義する必要性が高まりました。

<inttypes.h>の目的は、整数型のセットを提供することですその定義はマシン間で一貫しており、オペレーティングシステムや他の実装の特異性とは無関係ですtypedefを介して、さまざまなサイズの整数型を定義します。実装は、それらがサポートする標準C整数型または拡張として、自由にtypedefできます。このヘッダーを一貫して使用すると、プラットフォーム間でのユーザーのプログラムの移植性が大幅に向上します。

intint_fast16_tの主な違いは、後者にはこれらの「実装の特異性」がない可能性が高いことです。あなたはそれを次のようなものと考えるかもしれません:

intサイズの現在のOS /実装の「政治」は気にしません。少なくとも16ビットの最速の符号付き整数型を教えてください。

違いは、fastタイプは、よりも広い効率/最適化のための対応(fastなし)。しかし、C標準は、それらが実際に高速であることを決して保証しません。

C11、7.20.1.3最速の最小幅整数型

1次の各型は、少なくとも指定された幅を持つすべての整数型の中で動作するのに通常最も高速な整数型を示します262)。

2 typedef名int_fastN_tは、幅がN以上の最速の符号付き整数型を示します。typedef名uint_fastN_tは、幅がN以上の最速の符号なし整数型を示します。

262)指定されたタイプがすべての目的で最速であるとは限りません。あるタイプを別のタイプから選択する明確な根拠がない場合は、符号付きと幅の要件を満たす整数タイプを選択するだけです。

もう1つの違いは、fastおよびleast型が必須型であるのに対し、他の正確な型は幅のタイプはオプションです

3次のタイプが必要です。

2
P.P

一部のプラットフォームでは、16ビット値を使用すると、32ビット値を使用する場合よりもはるか遅くなる可能性があります[例: 8ビットまたは16ビットのストアでは、32ビットのロードを実行し、ロードされた値を変更して、結果を書き戻す必要があります]。 32ビット値の2倍の数の16ビット値をキャッシュに収めることができたとしても(32ビットシステムでは、16ビット値が32ビット値より速い通常の状況)、すべての書き込みが必要データ構造が書き込まれたよりもはるかに頻繁に読み取られない限り、読み取りの前に速度の利点はありません。このようなプラットフォームでは、int_fast16_tのような型は32ビットになる可能性があります。

そうは言っても、標準では残念ながらコンパイラーにとって最も役立つセマンティクスを許可していません。これは、アドレスが任意に16ビットタイプ以上として動作しないint_fast16_tタイプの変数を許可することです。タイプは、何が便利かによって異なります。たとえば、次のメソッドについて考えます。

int32_t blah(int32_t x)
{
  int_fast16_t y = x;
  return y;
}

多くのプラットフォームでは、メモリに格納されている16ビット整数は、レジスタに格納されている整数と同じように操作できますが、レジスタで16ビット演算を実行するための命令はありません。メモリに格納されているint_fast16_t変数が-32768〜+32767しか保持できない場合、同じ制限がレジスタに格納されているint_fast16_t変数に適用されます。サイズが大きすぎる値を保持するには小さすぎる符号付き整数型に強制変換するのは実装定義の動作であるため、上記のコードでは、返す前にxの下位16ビットに符号拡張する命令を追加せざるを得ません。規格がそのような型を許可している場合、柔軟な「少なくとも16ビットだが便利な場合はもっと多い」型は、そのような命令の必要性をなくすことができます。

1
supercat

2つのタイプの違いの例:8ビット、16ビット、32ビット、64ビットの演算が同等に高速であるアーキテクチャがあるとします。 (i386が近づきます。)次に、実装者はLLP64モデルを使用するか、さらにはプログラマがILP64、LP64、LLP64のいずれかを選択できるようにします。 sizeof(int) <= sizeof(void*) <= sizeof(long)。 64ビットの実装は、これらの前提の少なくとも1つに違反する必要があります。

その場合、intはおそらく32ビット幅になります。これは、他のシステムからのコードを最小限に抑えるためですが、uint_fast16_tは依然として16ビット幅で、スペースを節約できます。

1
Davislor