size_t型 - サイズを表す型
size_t型はサイズを表す型です。16bit以上の符号なし整数であることが、仕様上での必要な条件です。
32bitアドレス空間を扱う処理系では、符号なし32bit整数、64bitアドレス空間を扱う処理系では、符号なし64bit整数として定義されていると想定してください。
// サイズを表す型 size_t
そもそもsize_t型が意図しているサイズって何よ?
size_t型に出会ってわからないのは、サイズっていうけど、そもそもsize_t型が意図しているサイズって何よということではないでしょうか?
意図はおそらく、アドレス空間のサイズの抽象化です。32bitCPUであれば、扱えるメモリ空間が32bitで、64bitCPUであれば、扱えるメモリ空間は64bitです。
これらを抽象化して、同一のソースコードで、表現できるようにしたいということが、size_tの意図だと思われます。
size_t型の最大値
size_t型の最大値はSIZE_MAXで定義されています。
64bitのLinuxの環境で、SIZE_MAXを出力してみたサンプルです。%zuは、size_t型の値をポータブルに出力できる書式指定子です。
#include <stdio.h> #include <stdint.h> int main(void) { printf("%zu\n", SIZE_MAX); }
出力結果です。
18446744073709551615
この値以下であれば、その処理系で安全につかえるsize_tの値です。たとえば、callocの引数など。ただし、実際のメモリが足りるかどうかは、別の問題です。
仕様上安全かどうかと、実際の物理的な環境において安全かは、別の問題ですので、分けて考えましょう。
標準関数の引数におけるsize_t型
標準関数の引数には、strlenやmemcpy関数やcalloc関数など、size_t型で受け取るものがたくさんあります。
size_t strlen(const char *s); void *memcpy(void *buf1, const void *buf2, size_t n); void *calloc(size_t n, size_t size);
結局、私たちは、何を渡しておけば、大丈夫といえるのでしょうか?
すべての環境が32bit以上であるということを、前提にしてしまうと、32bit環境以上で、安全に動作させるには、符号なし32bit整数型以下で扱うと安全です。
ただし、整数を扱う場合は、まず符号あり32bit整数型のint32_tで扱うということを考えると、符号あり32bit整数型の最大値以下で扱うのがよいでしょう。
結論を書くと、size_t型の引数に渡す値は、int32_tで扱い、0以上、2147483647以下の値であること。
作成する文字列や配列のサイズも、2147483647以下であること。
このようにコーディングすると、広い環境でポータブルに動き、size_tについて迷ったり考えたりする必要が、かなり少なくなります。
#include <stdlib.h> int main(void) { int32_t length = 100; void* memory_block = calloc(sizeof(int32_t), length); free(memory_block); }