言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

C言語辞典

  1. トップページ
  2. C言語辞典
  3. sizeof

sizeof

対応: C89(1989)

『sizeof』演算子は、データ型や変数がメモリ上で占めるバイト数を返します。環境依存のサイズをコード内に直接書くことなく、移植性の高いプログラムを書くために活用されます。

構文

// 型のサイズをバイト数で返します。
sizeof(型)

// 変数のサイズをバイト数で返します。
sizeof(変数名)
sizeof 変数名 // 変数の場合は括弧を省略できます。

// 配列全体のバイト数を返します。
sizeof(配列名)

// 配列の要素数を求めるイディオムです。
sizeof(配列名) / sizeof(配列名[0])

主な型のサイズ(64ビット環境の目安)

サイズ概要
char1バイトC言語では『sizeof(char)』は常に1と定義されています。
short2バイトほぼすべての環境で2バイトです。
int4バイト多くの環境で4バイトですが、規格では『short以上』と定められています。
long4〜8バイトWindowsの64ビットでは4バイト、Linux/macOSの64ビットでは8バイトです。
long long8バイトC99で追加された型です。64ビット整数を保証します。
float4バイトIEEE 754単精度浮動小数点数です。
double8バイトIEEE 754倍精度浮動小数点数です。
pointer4〜8バイト32ビット環境では4バイト、64ビット環境では8バイトです。

サンプルコード

sample_sizeof.c
#include <stdio.h>

int main(void) {
    printf("char: %zu バイト\n", sizeof(char));
    printf("short: %zu バイト\n", sizeof(short));
    printf("int: %zu バイト\n", sizeof(int));
    printf("long: %zu バイト\n", sizeof(long));
    printf("long long: %zu バイト\n", sizeof(long long));
    printf("float: %zu バイト\n", sizeof(float));
    printf("double: %zu バイト\n", sizeof(double));

    int n = 42;
    double x = 3.14;
    printf("変数 n のサイズ: %zu バイト\n", sizeof n);
    printf("変数 x のサイズ: %zu バイト\n", sizeof x);

    int scores[10];
    printf("配列のサイズ: %zu バイト\n", sizeof(scores)); /* 40バイト(10×4)*/
    printf("配列の要素数: %zu\n", sizeof(scores) / sizeof(scores[0]));

    int *p = &n;
    printf("ポインタのサイズ: %zu バイト\n", sizeof(p)); /* 64ビット環境では 8 */

    return 0;
}

コンパイルして実行すると次のようになります。

gcc sizeof.c -o sizeof
./sizeof
char: 1 バイト
short: 2 バイト
int: 4 バイト
long: 8 バイト
long long: 8 バイト
float: 4 バイト
double: 8 バイト
変数 n のサイズ: 4 バイト
変数 x のサイズ: 8 バイト
配列のサイズ: 40 バイト
配列の要素数: 10
ポインタのサイズ: 8 バイト

構造体のサイズとパディング

構造体のサイズはメンバを単純に足した値より大きいことがあります。アライメント(境界整列)のためコンパイラがパディング(詰め物)を挿入するためです。

sizeof_struct.c
#include <stdio.h>

typedef struct {
    char a; /* 1バイト */
    int b; /* 4バイト(3バイトのパディングが入ることがある) */
    char c; /* 1バイト */
    /* 末尾にもパディングが入ることがある */
} WithPadding;

typedef struct {
    int b; /* 4バイト */
    char a; /* 1バイト */
    char c; /* 1バイト */
    /* 2バイトのパディング */
} Reordered;

int main(void) {
    printf("WithPadding: %zu バイト\n", sizeof(WithPadding));
    printf("Reordered: %zu バイト\n", sizeof(Reordered));
    return 0;
}

コンパイルして実行すると次のようになります。

gcc sizeof_struct.c -o sizeof_struct
./sizeof_struct
WithPadding: 12 バイト
Reordered: 8 バイト

よくあるミス

よくあるミス: 関数内で sizeof を使って配列サイズを得ようとする

配列を関数に渡すとポインタに変換されます。関数内で sizeof を使うとポインタのサイズ(8バイトなど)が返り、配列全体のサイズにはなりません。

sizeof_array_ng.c
#include <stdio.h>

void print_size(int arr[]) {
    /* NG: ポインタのサイズ(8)が返る */
    printf("関数内: %zu バイト\n", sizeof(arr));
}

int main(void) {
    int arr[5] = {1, 2, 3, 4, 5};
    printf("main 内: %zu バイト\n", sizeof(arr)); /* 20 バイト */
    print_size(arr);
    return 0;
}

修正後は次の通りです。

gcc sizeof_array_ng.c -o sizeof_array_ng
./sizeof_array_ng
main 内: 20 バイト
関数内: 8 バイト
sizeof_array_ok.c
#include <stdio.h>

/* OK: 要素数を別引数として渡す */
void print_sum(const int *arr, int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) sum += arr[i];
    printf("合計: %d\n", sum);
}

int main(void) {
    int arr[5] = {10, 20, 30, 40, 50};
    int n = (int)(sizeof(arr) / sizeof(arr[0]));
    print_sum(arr, n); /* 『合計: 150』と出力されます。 */
    return 0;
}

修正後は次の通りです。

gcc sizeof_array_ok.c -o sizeof_array_ok
./sizeof_array_ok
合計: 150

概要

『sizeof』はコンパイル時に評価される演算子です(可変長配列に使う場合を除く)。返り値の型は『size_t』という符号なし整数型で、『printf』では『%zu』で出力します。

配列をポインタに代入したり関数に渡したりすると、『sizeof』はポインタ自体のサイズを返します。配列全体のサイズは、配列を直接渡したときのみ正しく取得できます。これは「配列のポインタへの減衰」と呼ばれる挙動です。

動的メモリ確保(『malloc()』)と組み合わせる際は、型のサイズをハードコードせず『sizeof(型)』を使うことで移植性が高まります。構造体のサイズも『sizeof』で取得できますが、アライメント(境界整列)のためパディングが挿入されることがあります。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。