私はsize_t
Cで混乱しています.私はそれがsizeof
演算子によって返されることを知っています. しかし、それは正確には何ですか?データ型ですか?
for
ループがあるとしましょう:
for(i = 0; i < some_size; i++)
またはを使用する必要がありますint i;
かsize_t i;
?
1999 ISO C 標準 (C99) によると、
size_t
少なくとも 16 ビットの符号なし整数型です (セクション 7.17 および 7.18.3 を参照)。
size_t
で定義されている C99 ISO/IEC 9899 標準など、いくつかの C/C++ 標準で定義されている符号なしデータ型stddef.h
です。1stdlib.h
このファイルは内部的にサブインクルードされているため、 をインクルードすることでさらにインポートできますstddef.h
。この型は、オブジェクトのサイズを表すために使用されます。サイズを取得または返すライブラリ関数は、サイズが の型であるか、戻り値の型を持っていることを期待しています
size_t
。さらに、最も頻繁に使用されるコンパイラベースの演算子 sizeof は、 と互換性のある定数値に評価される必要がありsize_t
ます。
暗黙的に、size_t
任意の配列インデックスを保持することが保証されている型です。
size_t
符号なしタイプです。したがって、負の値 (<0) を表すことはできません。何かを数えるときに使用し、それが負になることはないと確信しています。たとえば、文字列の長さは少なくとも 0 である必要がstrlen()
あるため、a を返します。size_t
あなたの例では、ループ インデックスが常に 0 より大きい場合size_t
、または他の符号なしデータ型を使用するのが理にかなっています。
オブジェクトを使用するときsize_t
は、算術演算を含め、オブジェクトが使用されるすべてのコンテキストで負でない値が必要であることを確認する必要があります。たとえば、あなたが持っているとしましょう:
size_t s1 = strlen(str1);
size_t s2 = strlen(str2);
と の長さの差を見つけたいとしstr2
ますstr1
。次のことはできません。
int diff = s2 - s1; /* bad */
これは、符号なしの型で計算が行われるため、 のdiff
場合でも、 に代入される値が常に正の数になるためです。この場合、ユースケースによっては、 と に(または) をs2 < s1
使用した方がよい場合があります。int
long long
s1
s2
C/POSIX には を使用できる/使用すべき関数がいくつかありますがsize_t
、歴史的な理由により使用しません。たとえば、 の 2 番目のパラメータfgets
は理想的にはである必要size_t
がありますが、実際にはint
です。
あなたが経験型なら、
echo | gcc -E -xc -include 'stddef.h' - | grep size_t
Ubuntu 14.04 64 ビット GCC 4.8 の出力:
typedef long unsigned int size_t;
GCC 4.2stddef.h
の glibc ではなく、GCC によって提供されることに注意してください。src/gcc/ginclude/stddef.h
興味深い C99 の外観
malloc
は引数として取るsize_t
ので、割り当てられる最大サイズを決定します。
また、 からも返されるsizeof
ため、配列の最大サイズを制限していると思います。
参照: C の配列の最大サイズは?
types.hのマンページには次のように書かれています。
size_t は符号なし整数型でなければなりません
size_t
交換可能ではありint
ません。たとえば、64 ビットの Linux ではsize_t
、サイズは 64 ビット (つまりsizeof(void*)
) ですが、int
32 ビットです。
size_t
また、署名されていないことに注意してください。署名されたバージョンが必要な場合はssize_t
、一部のプラットフォームにあり、例により関連性があります。
原則として、int
ほとんどの一般的なケースに使用し、特定の必要がある場合にのみsize_t
/を使用することをお勧めします (たとえば)。ssize_t
mmap()
一般に、0 から開始して上に向かっている場合は、負の値の状況に陥るオーバーフローを避けるために、常に符号なし型を使用してください。これは非常に重要です。なぜなら、配列の境界がたまたまループの最大値よりも小さく、ループの最大値がたまたま型の最大値よりも大きい場合、負の値にラップアラウンドし、セグメンテーション フォールト(SIGSEGV)が発生する可能性があるためです。 )。そのため、一般に、0 から開始して上に向かうループに int を使用しないでください。無印を使用。
これはプラットフォーム固有のtypedef
. たとえば、特定のマシンでは、unsigned int
またはの場合がありますunsigned long
。コードの移植性を高めるために、この定義を使用する必要があります。
私の理解でsize_t
は、unsigned
ビット サイズがネイティブ アーキテクチャのポインタを保持するのに十分な大きさの整数です。
そう:
sizeof(size_t) >= sizeof(void*)