私は、現代のCおよびC++コードがint
/size_t
の代わりにunsigned int
をほとんどどこでも使用しているように見えることに気づいています - C文字列関数のパラメータからSTLまで。私はこの理由とそれがもたらす利点について興味があります。
Classic C(Brian KernighanとDennis RitchieによってThe C Programming Language、1978年、Prentice-Hallによって説明されたCの初期の方言)はsize_t
を提供しませんでした。 C標準化委員会は移植性の問題を排除するためにsize_t
を導入しました
つまり、size_t
は負になることはなく、ターゲットプラットフォーム上で可能な最大のオブジェクトのサイズを表すのに十分な大きさで、大きすぎない符号付き整数型であることがtypedefされているため、パフォーマンスが最大になります。
サイズが負になることは絶対にありません。実際、size_t
は符号なし型です。また、size_t
は符号なしであるため、符号付き整数の他のすべてのビットと同様に、符号ビットを使用して大きさを表すことができるため、対応する符号付き型の約2倍の大きさの数値を格納できます。もう1つビットを取得すると、表現できる数値の範囲に約2の係数を掛けます。
それで、あなたは尋ねます、なぜunsigned int
を使わないのですか?十分に大きい数を保持することができないかもしれません。 unsigned int
が32ビットの実装では、それが表すことができる最大数は4294967295
です。 IP16L32などの一部のプロセッサは、4294967295
バイトより大きいオブジェクトをコピーできます。
それで、あなたは尋ねます、なぜunsigned long int
を使わないのですか?一部のプラットフォームではパフォーマンスが低下します。標準Cでは、long
が少なくとも32ビットを占めることを要求しています。 IP16L32プラットフォームは、それぞれ32ビット長を1組の16ビットワードとして実装します。これらのプラットフォーム上のほとんどすべての32ビット演算子は、2つの16ビットチャンクで32ビットを処理するため、2つ以上の命令を必要とします。たとえば、32ビット長を移動するには、通常、2つの機械命令が必要です。1つは各16ビットチャンクを移動するための命令です。
size_t
を使用すると、このパフォーマンスの低下を回避できます。 この素晴らしい記事 によると、Type size_t
は、符号なし整数型のエイリアスで、通常はunsigned int
またはunsigned long
ですが、おそらくunsigned long long
でさえあるtypedefです。各Standard C実装は、符号なし整数を選択することになっています。ターゲットプラットフォーム上で可能な最大のオブジェクトのサイズを表すのに十分な大きさ - ただし必要以上の大きさではない - 」
Size_t型は、sizeof演算子によって返される型です。ホストマシンでサポートされている任意のメモリ範囲のサイズをバイト単位で表現できる符号なし整数です。 ptrdiff_tは、sizeof(ptrdiff_t)とsizeof(size_t)が等しくなるような符号付き整数値であるという点で(通常)ptrdiff_tに関連しています。
Cコードを書くときは、常にメモリ範囲を扱うときはいつもsize_tを使うべきです。
一方、int型は基本的に、ホストマシンが整数演算を最も効率的に実行するために使用できる(符号付き)整数値のサイズとして定義されています。たとえば、多くの古いPCタイプのコンピュータでは、sizeof(size_t)の値は4(バイト)になりますが、sizeof(int)の値は2(バイト)になります。 CPUは最大4 GiBの(論理)メモリ空間を処理できますが、16ビット演算は32ビット演算より高速です。
実際の精度はコンパイラオプションとマシンアーキテクチャの両方に強く依存するため、int型は効率を気にする場合にのみ使用してください。特にC規格では、次の不変式を指定しています。sizeof(char)<= sizeof(short)<= sizeof(int)<= sizeof(long)これらのプリミティブ型.
注:これはJavaの場合と同じではありません(実際には、 'char'、 'byte'、 'short'、 'int'、および 'long'の各型のビット精度が指定されています)。
Size_t型は、可能性のあるオブジェクトのサイズを格納するのに十分な大きさでなければなりません。 unsigned intはその条件を満たす必要はありません。
例えば64ビットシステムではintとunsigned intは32ビット幅かもしれませんが、size_tは4Gより大きな数を格納するのに十分な大きさでなければなりません。
Glibcマニュアル0.02からのこの抜粋は、トピックを調査するときにも関連があります。
Size_t型およびリリース2.4より前のGCCのバージョンには潜在的な問題があります。 ANSI Cは、size_tが常に符号なしの型であることを要求します。既存のシステムのヘッダファイルとの互換性のために、GCCはstddef.h' to be whatever type the system's
sys/types.hでsize_tを定義します。 `sys/types.h 'でsize_tを定義しているほとんどのUnixシステムは、それを符号付き型として定義しています。ライブラリ内の一部のコードは、size_tが符号なしタイプであることに依存しており、それが署名されていると正しく機能しません。
Size_tが符号なしであることを期待するGNU Cライブラリコードは正しいです。符号付き型としてのsize_tの定義が正しくありません。バージョン2.4では、GCCは常にsize_tを符号なしの型として、そしてfixincludes' script will massage the system's
sys/types.h 'をそれと矛盾しないように定義する予定です。
それまでの間、GNU Cライブラリをコンパイルするときに、GCCにsize_tに符号なし型を使用するように明示的に指示することで、この問題を回避します。 `configure 'はGCCがsize_tのためにどのタイプを使用するかを自動的に検出し、必要ならばそれを上書きするように調整します。
私のコンパイラが32ビットに設定されている場合、size_t
はunsigned int
のtypedef以外の何ものでもありません。私のコンパイラが64ビットに設定されている場合、size_t
はunsigned long long
のtypedef以外の何ものでもありません。