C言語

キャスト演算子とsizeof演算子の基本

C言語を学んでいくと、「型を変換したい」「データの大きさを知りたい」という場面が出てきます。
そんなときに使うのが、キャスト演算子とsizeof 演算子です。
今回は、このキャスト演算子とsizeof演算子の基本的な使い方について解説します。

キャスト演算子(型変換)とは

キャスト演算子(型変換)とは、変数の型を一時的に“別の型として扱う”ための仕組みです。

キャスト演算子の構文は次の通りです。

(型名) 式

式を( )で指定した型に変換します。

次にキャストを行わない場合の例として、「小数と整数の混在による計算」のプログラムを見てみましょう。

int a = 5;
int b = 2;
double ans;

ans = a / b;  // 2 になってしまう(小数点以下切り捨て)

整数 ÷ 整数 の計算は、結果も整数になってしまうため、小数以下が失われます。
なぜなら、C言語は、計算する前に“式の型”を決めてから計算するというルールがあるからです。

代入の変数の型に関わらず、int型とint型の結果はint型と扱われます。
従って、ans には、小数点が切り捨てられて 2 となります。

型が違う者同士の演算

では、型が違う者同士を演算したらどうなるでしょうか。
C言語では、異なる型で計算するときは、より表示範囲の広い型(大きい型)に合わせて計算するというルールがあります。

例えば、下記では、float(4バイト)と、short(2バイト)では、float のほうが大きい型なので、結果は、小数点ありの値になります。

float a = 5.5;
short b = 2;
float ans;

では、同じ大きさの型(例えば、int(4 バイト) と float(4 バイト)、または、int(4バイト) と unsigned int(4バイト)など)はどちらに合わせて計算するのでしょうか。
それは、基本的に次のように決められます。

  • C言語では「バイトサイズ」ではなく「型の優先順位」で型が決まる
  • 同じ 4 バイトでも階級が違う
  • float > int
  • float > long(4バイトの場合)
  • int と unsigned int は unsigned に寄せられることが多い

ただ、どちらの型に合わせるかはコンパイラ実装に依存する場合がありますので、正確に知りたい場合は、使用するコンパイラの仕様を確認してください。

キャスト演算子を使った例

先ほどの「小数と整数の混在による計算」のプログラムから、キャスト演算子を使用した場合の例を示します。

int a = 5;
int b = 2;
double ans;

ans = (double)a / b;  // 変数aが一時的にdouble型になる

int型の変数 a がキャストにより一時的にdouble型になるため、表示範囲の広い型(大きい型)に合わせて計算するというルールにより、計算結果がdouble型に合わせて計算されることで、変数 ans は、小数点ありの値が代入されます。

キャスト演算子は、一時的に変換するだけなので、変数の型はかわりません。

sizeof演算子とは

次にsizeof演算子について紹介します。
sizeof演算子とは、変数や型が「何バイトの大きさか」を教えてくれる演算子です。
構文は次の通りです。

sizeof(型名)
sizeof(変数名)
sizeof 変数名  // 変数名の場合は、()は無くてもOK

sizeof演算子を使った例

型のサイズや変数のサイズを表示するプログラムを見てみましょう。

#include <stdio.h>

int main(void)
{
    int a = 10;
    double b = 3.14;
    char c = 'A';
    int array[5];

    printf("=== sizeof の基本 ===\n");
    printf("sizeof(int)        : %zu バイト\n", sizeof(int));        // 型名(括弧必須)
    printf("sizeof(double)     : %zu バイト\n", sizeof(double));
    printf("sizeof(char)       : %zu バイト\n\n", sizeof(char));

    printf("=== sizeof 変数(括弧あり) ===\n");
    printf("sizeof(a)          : %zu バイト\n", sizeof(a));          // 変数(括弧あり)
    printf("sizeof(b)          : %zu バイト\n", sizeof(b));
    printf("sizeof(c)          : %zu バイト\n\n", sizeof(c));

    printf("=== sizeof 変数(括弧なし) ===\n");
    printf("sizeof a           : %zu バイト\n", sizeof a);            // 変数(括弧なし)
    printf("sizeof b           : %zu バイト\n", sizeof b);
    printf("sizeof c           : %zu バイト\n\n", sizeof c);

    printf("=== 配列 ===\n");
    printf("sizeof(array)      : %zu バイト\n", sizeof(array));       // 配列全体のサイズ
    printf("sizeof(array[0])   : %zu バイト\n", sizeof(array[0]));    // 配列の要素1つのサイズ
    printf("配列の要素数        : %zu\n", sizeof(array) / sizeof(array[0]));

    return 0;
}

実行結果は次の通りです。

=== sizeof の基本 ===
sizeof(int)        : 4 バイト
sizeof(double)     : 8 バイト
sizeof(char)       : 1 バイト

=== sizeof 変数(括弧あり) ===
sizeof(a)          : 4 バイト
sizeof(b)          : 8 バイト
sizeof(c)          : 1 バイト

=== sizeof 変数(括弧なし) ===
sizeof a           : 4 バイト
sizeof b           : 8 バイト
sizeof c           : 1 バイト

=== 配列 ===
sizeof(array)      : 20 バイト
sizeof(array[0])   : 4 バイト
配列の要素数        : 5

このように、型や変数のサイズを求めることができます。

まとめ

キャスト演算子

  • (型名) 式 で一時的に型変換できる
  • 整数同士の計算に小数を含めたいときに使う
  • ビット演算・組み込みでもよく使う
  • 変換しても元の変数は変わらない

sizeof演算子

  • sizeof(型名) または sizeof 変数名
  • データのバイト数を知るために使う
  • 配列の「全体のサイズ」もわかる
  • sizeof(a)/sizeof(a[0])で要素数が求められる
  • 関数に渡すと配列はポインタに変わる点に注意

-C言語