回答:
size_t
タイプの結果である符号なし整数型であり、sizeof
オペレータ(及びoffsetof
あなたのシステムが処理できる最大のオブジェクト(たとえば、8GBのの静的配列)のサイズを格納するための十分な大きさであることが保証されるように、オペレータ)。
size_t
タイプは、より、より大きな等しい、または小さくてもよくunsigned int
、そして、あなたのコンパイラが最適化のためにそれについての仮定を行うことがあります。
より正確な情報は、C99標準のセクション7.17にあります。その草案は、インターネット上でpdf形式で入手できます。C11標準のセクション7.19にも、pdf草案として入手できます。
size_t
!そうでない場合、誰がしますか?
クラシックC(ブライアンカーニハンとデニスリッチーがThe C Programming Language、Prentice-Hall、1978年に記述した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ビットの長さを16ビットワードのペアとして実装します。これらのプラットフォームのほとんどすべての32ビットオペレーターは、32ビットを2つの16ビットチャンクで処理するため、2つ以上の命令が必要です。たとえば、32ビットのlongを移動するには、通常2つのマシン命令が必要です。1つは各16ビットのチャンクを移動するためのものです。
を使用するとsize_t
、このパフォーマンスの低下を回避できます。この素晴らしい記事によれば、「Type size_t
は、通常はunsigned int
またはのunsigned long
、一部の符号なし整数型のエイリアスであるtypedefですが、場合によってはunsigned long long
です。各標準C実装は、十分な大きさの符号なし整数を選択することになっていますが、必要以上に大きくはありません。ターゲットプラットフォーム上で可能な最大のオブジェクトのサイズを表します。」
unsigned int
システムによって異なります。それは少なくとも 65536
である必要がありますが、それは一般的で4294967295
あり18446744073709551615
、一部のシステムでは(2 ** 64-1)になる可能性があります。
unsigned char
)に関する絶対的な保証がすべて削除されたように見えます。標準には、文字列「65535」または「65536」がどこにも含まれていないようです。「+ 32767」は、で表現可能な最大の整数としてノートでのみ発生します(1.9:9)int
。INT_MAX
それより小さくても保証はありません!
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(バイト)です。16ビット演算は32ビット演算よりも高速でしたが、CPUは最大4 GiBの(論理)メモリ空間を処理できました。
int型は、実際の精度がコンパイラオプションとマシンアーキテクチャの両方に強く依存するため、効率を重視する場合にのみ使用してください。特にC標準では、次の不変式を指定しています。これらのプリミティブ型。
注:これはJavaの場合とは異なります(実際には、「char」、「byte」、「short」、「int」、および「long」の各タイプのビット精度を指定します)。
size_t
は、任意の単一オブジェクト(例:数値、配列、構造)のサイズを表すことができます。メモリ全体の範囲を超えている可能性がありますsize_t
size_t
がそうであることを意味します-あなたがそれを意味しないことを願っています。ほとんどの場合、アドレス空間のカーディナリティ+移植性が問題になる配列については扱いません。これらの場合、あなたは取るでしょうsize_t
。他のすべての場合では、(符号付き)整数からインデックスを取り出します。符号なしの予期せぬアンダーフロー動作が原因で発生する混乱(警告なし)は、他のケースで発生する可能性のある移植性の問題よりも一般的であり、悪いためです。
タイプsize_tは、可能なオブジェクトのサイズを格納するのに十分な大きさでなければなりません。符号なし整数は、その条件を満たす必要はありません。
たとえば、64ビットシステムでは、intとunsigned intは32ビット幅ですが、size_tは4Gより大きい数値を格納するのに十分な大きさでなければなりません。
size_t
sizeof(X)が4Gより大きい値を生成するようなコンパイラーがタイプXを受け入れることができる場合のみ、私はその大きさである必要があると思います。ほとんどのコンパイラは、たとえばを拒否しtypedef unsigned char foo[1000000000000LL][1000000000000LL]
、foo[65536][65536];
実装で定義された制限を超えた場合は合法的に拒否される可能性さえあります。
glibcマニュアル0.02からのこの抜粋は、トピックを調査するときにも関連する可能性があります。
リリース2.4より前のGCCのsize_tタイプとバージョンに潜在的な問題があります。ANSI Cでは、size_tは常に符号なしの型である必要があります。既存のシステムのヘッダーファイルとの互換性のために、GCCはsize_tをstddef.h' to be whatever type the system's
sys / types.hで定義し、それがそうであることを定義します。`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ライブラリをコンパイルするときに、size_tに符号なしの型を使用するようにGCCに明示的に指示することで、この問題を回避します。`configure 'は、GCCがsize_tに使用するタイプを自動的に検出し、必要に応じてそれを上書きします。
コンパイラが32ビットに設定されているsize_t
場合、のtypedefにすぎませんunsigned int
。コンパイラが64ビットに設定されている場合size_t
は、のtypedefにすぎませんunsigned long long
。
unsigned long
一部のOSでは両方の場合と同様に定義できます。
size_tは、ポインターのサイズです。
したがって、32ビットまたは一般的なILP32(整数、ロング、ポインター)モデルでは、size_tは32ビットです。64ビットまたは一般的なLP64(long、ポインター)モデルでは、size_tは64ビットです(整数は32ビットのままです)。
他のモデルもありますが、これらはg ++が使用するものです(少なくともデフォルトでは)。
size_t
通常は同じですが、ポインタと同じサイズである必要はありません。ポインタは、メモリ内の任意の場所を指すことができる必要があります。size_t
最大の単一オブジェクトのサイズを表すのに十分な大きさでなければなりません。