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);
}

関連情報