sizeof
は、C言語において非常に重要な演算子で、変数やデータ型が占めるメモリのサイズをバイト単位で取得するために使用されます。この演算子は、メモリの効率的な管理や、データ型や構造体のポータビリティ(可搬性)を確保するために欠かせません。この記事では、sizeof
の使い方、メモリの管理方法、およびどのようにして効率的にメモリを予約するかについて詳しく解説します。
1. sizeof
演算子の基本的な使い方
sizeof
演算子は、式やデータ型に対して使用され、対応するメモリのサイズをバイト単位で返します。たとえば、int
型やchar
型のサイズを確認する際に使用します。

例 1: 基本的な使用例
c#include
int main() {
int a = 10;
printf("int型のサイズ: %zu バイト\n", sizeof(int)); // int型のサイズを表示
printf("aのサイズ: %zu バイト\n", sizeof(a)); // 変数aのサイズを表示
return 0;
}
ここでは、sizeof(int)
は通常4バイト(システムによって異なる場合があります)を返し、sizeof(a)
は変数a
のメモリサイズを返します。通常、a
のサイズもint
型と同じですが、これは変数がどのデータ型を使っているかに依存します。
例 2: 他のデータ型
c#include
int main() {
char c = 'A';
double d = 3.14;
printf("char型のサイズ: %zu バイト\n", sizeof(char)); // char型のサイズ
printf("double型のサイズ: %zu バイト\n", sizeof(double)); // double型のサイズ
return 0;
}
一般的に、char
型は1バイト、double
型は8バイト(システムによる)となります。
2. sizeof
とポインタ
sizeof
はポインタに対しても使用することができますが、ポインタの実際のサイズ(ポインタ変数そのもののサイズ)と、ポインタが指している先のデータのサイズを区別する必要があります。
例 3: ポインタとsizeof
c#include
int main() {
int a = 10;
int *ptr = &a;
printf("ポインタ変数のサイズ: %zu バイト\n", sizeof(ptr)); // ポインタそのもののサイズ
printf("ポインタが指す値のサイズ: %zu バイト\n", sizeof(*ptr)); // ポインタが指している先の値のサイズ
return 0;
}
上記の例では、sizeof(ptr)
は通常4バイト(32ビットシステムの場合)ですが、sizeof(*ptr)
はint
型のサイズ(通常4バイト)を返します。
3. sizeof
と配列
配列に対してsizeof
を使用することで、配列全体のサイズを取得することができます。しかし、ポインタとして配列を渡すと、sizeof
はポインタのサイズを返すことになります。
例 4: 配列とsizeof
c#include
int main() {
int arr[10];
printf("配列のサイズ: %zu バイト\n", sizeof(arr)); // 配列全体のサイズ
printf("配列の1要素のサイズ: %zu バイト\n", sizeof(arr[0])); // 1要素のサイズ
return 0;
}
ここでは、sizeof(arr)
はarr
配列全体のサイズを返します。arr
が10個のint
型の要素を持つ場合、通常は10 * sizeof(int)
のサイズ(例えば40バイト)になります。
しかし、配列を関数に渡すと、配列はポインタとして渡されるため、sizeof
が異なる結果を返すことに注意が必要です。
例 5: 配列を関数に渡す
c#include
void printSize(int arr[]) {
printf("関数内での配列のサイズ: %zu バイト\n", sizeof(arr));
}
int main() {
int arr[10];
printf("main関数での配列のサイズ: %zu バイト\n", sizeof(arr));
printSize(arr); // 配列を関数に渡す
return 0;
}
この場合、sizeof(arr)
は関数内ではポインタとして解釈され、通常4バイト(32ビットシステムの場合)になります。一方、main
関数内では配列全体のサイズが返されます。
4. sizeof
と構造体
構造体に対してもsizeof
を使用できます。構造体のサイズは、各メンバーの型のサイズの合計にパディング(メモリの整列)が加わったものになります。これにより、構造体のサイズはそのメンバーのサイズの合計と異なることがあります。
例 6: 構造体とsizeof
c#include
struct Person {
char name[50];
int age;
};
int main() {
struct Person person;
printf("構造体のサイズ: %zu バイト\n", sizeof(person)); // 構造体のサイズ
return 0;
}
上記の例では、struct Person
にはchar[50]
とint
が含まれていますが、構造体のサイズはこれらのサイズの合計にパディングを加えたものになります。通常、char[50]
は50バイト、int
は4バイトですが、メモリの整列によって、構造体のサイズは54バイト(システムによる)になる場合があります。
5. sizeof
を使ったメモリの予約
sizeof
を使用して、動的にメモリを予約する際に便利です。malloc
やcalloc
を使用する際に、sizeof
を活用して適切なメモリを確保します。
例 7: メモリの動的確保
c#include
#include
int main() {
int *arr = (int *)malloc(10 * sizeof(int)); // int型の配列10個分のメモリを動的に確保
if (arr == NULL) {
printf("メモリの確保に失敗しました。\n");
return 1;
}
// 確保したメモリを使用する
arr[0] = 1;
printf("arr[0]: %d\n", arr[0]);
// メモリの解放
free(arr);
return 0;
}
この場合、malloc(10 * sizeof(int))
を使用して、int
型の配列10個分のメモリを動的に確保しています。sizeof
を使うことで、プログラムが異なるプラットフォームでも正しく動作するようになります。
6. 結論
sizeof
演算子は、C言語においてメモリサイズを確認したり、動的メモリ確保の際に非常に便利なツールです。適切に使用することで、メモリの効率的な管理が可能となり、ポータブルで信頼性の高いプログラムを書くことができます。特に、データ型や構造体のサイズを把握することは、クロスプラットフォームでのプログラム開発において欠かせません。