sizeofは、指定された型の大きさ(バイト数)を返す、C言語の単項演算子。
sizeofの値の型はsize_t型(strlen()関数とかと一緒)。
説明 | 例 | |
---|---|---|
sizeof(型名) |
型のサイズを返す。 | sizeof(int) |
sizeof 変数名 |
変数の型のサイズを返す。 | int n; |
sizeof 値 |
値の型のサイズを返す。 | sizeof "abc" |
型を指定する場合は、型名を括弧でくくる必要がある。
それ以外の場合は括弧でくくる必要は無いが、くくっている人が多い。
これはreturnを使うときに「return 値;
」と書けば済むのを「return(値);
」と書くのに似ている。
return文は「文」であって「関数」じゃないから、括弧を付ける必要は無い。
sizeofの場合は誤解を招きそうなので、括弧を付けた方がいいかもね。「size_t sz = sizeof "abc" - 1;
」
sizeofは、型のサイズを返す。
だから、ポインター変数を指定した場合、ポインターの指している先に確保されているメモリサイズを返すのではなく、ポインターのサイズ(32bitCPUならたぶん4)が返る。
例 | 解説 |
---|---|
char *p = (char*)malloc(256); size_t sz = sizeof(p); |
malloc()で確保されたサイズ(256)ではなく、変数pの型(char* )のサイズ(4)が返る。 |
size_t sz = sizeof("abcd"); |
"abcd"の型はconst char[5] ('a','b','c','d'の4文字分に'\0'の分が入っているから)。したがって5が返る。文字数を数えたいならstrlen()を使う。 |
const char *p = "abcd"; size_t sz = sizeof(p); |
変数pの型のサイズ(4)が返る。上記のsizeof("abcd")と同じにはならない。 |
sizeof演算子の演算が評価(実行)されるのは、+や-と同様の演算子だから当然実行時。
しかし大抵は固定値になるので、コンパイル時に最適化されて定数になる。
実行時に値が変わるのは、例えば以下のような場合。
size_t test(int n) { int array[n]; //動的に確保される配列 return sizeof(array); }
nの値に応じたサイズがちゃんと取得できる。
sizeofが計算されるのは実行時(あるいはコンパイル時)であり、プリプロセス(コンパイルの前処理)時ではない。
したがって、以下のような使い方は出来ない。
#if sizeof(int) == 4 〜 #endif
たいていは固定値になるんだから、定数になる時だけは出来ても良さそう/出来ると便利な気はするけど…。
sizeofが型のバイト数を返すのを利用して配列の個数を計算するのは定石。
TYPE array[] = { … //配列の初期化 }; int i; for(i=0; i < sizeof(array) / sizeof(*array); i++) { TYPE *p = &array[i]; 〜 }
この方法は、サイズの決まった配列変数(型 変数[]
)でないと使えない。ポインター変数(型 *変数
)には使えない。