22 型変換

C言語では異なる型の値が混在するとき、自動または明示的に型変換が行われる。
意図しない変換はバグの原因になるため、仕組みをきちんと理解しておく。


22-1 暗黙的型変換

代入や演算で型が自動的に変換されることを暗黙的型変換(implicit conversion)という。

int    a = 5;
double b = a;   /* int → double に自動変換される */

式の中で異なる型が混在する場合も自動変換が起きる。

int    i = 2;
double d = 3.5;
double result = i + d;   /* i が double に変換されてから加算 → 5.5 */

型の「格上げ」の方向

精度の低い型が高い型に合わせて変換される(情報を失わない方向)。

char → int → long → float → double
✅ int と double が混在したとき、int が double に「格上げ」されてから計算される。

22-2 暗黙的型変換の落とし穴

最も起きやすいバグが「整数同士で割り算してから double に代入する」パターン。

22_01_implicit_bug.c
#include <stdio.h>

int main(void)
{
    int a = 3, b = 2;
    double result = a / b;    /* 整数同士で先に計算 → 1 → 1.0 に変換 */
    printf("%.1f\n", result); /* 1.0 と表示される(1.5 ではない!)*/
    return 0;
}
1.0
a / b の時点で両方 int なので整数除算(切り捨て)になる。
結果の 1 が double に変換されて 1.0 になる。期待の 1.5 にはならない。

22-3 明示的型変換(キャスト)

意図的に型を変換することを明示的型変換(explicit conversion)またはキャストという。

(変換後の型) 値
22_02_cast.c
#include <stdio.h>

int main(void)
{
    int a = 3, b = 2;

    /* a を double にキャストしてから除算 */
    double result = (double)a / b;
    printf("%.1f\n", result);  /* 1.5 と表示される */

    /* 実数を整数に変換(小数点以下切り捨て) */
    double pi = 3.14159;
    int n = (int)pi;
    printf("%d\n", n);  /* 3 と表示される */

    return 0;
}
1.5
3
(double)a / b は「a を double にしてから b と割る」。
片方が double になると、もう片方も自動的に double に変換される。
(double)(a / b) と書くと整数除算した後に変換するため 1.0 になる。
キャストの位置(どこに書くか)が重要。

22-4 まとめ:どう書けばどうなるか

コード計算の流れ結果
double r = 3 / 2;int÷int=1 → double変換1.0
double r = 3.0 / 2;double÷int → intをdoubleに格上げ1.5
double r = (double)3 / 2;double÷int → intをdoubleに格上げ1.5
double r = (double)(3 / 2);int÷int=1 → double変換1.0
int n = (int)3.9;小数点以下切り捨て3

22-5 演習

📝 演習① 正しく 1.5 を出力する

次のコードを修正して 1.5 と出力されるようにせよ。

#include <stdio.h>

int main(void)
{
    int a = 3, b = 2;
    double result = a / b;
    printf("%.1f\n", result);
    return 0;
}
答えの例を表示
double result = (double)a / b;   /* または 3.0 / b など */
📝 演習② 5人の平均点を小数点以下1桁で表示

5つの整数(点数)を入力し、平均を小数点以下1桁で表示するプログラムを作れ。
キャストを使って正確な実数で計算すること。

22_03_average.c
#include <stdio.h>

int main(void)
{
    int score[5], i, sum = 0;

    printf("5人の点数を入力してください:\n");
    for (i = 0; i < 5; i++) {
        printf("score[%d]: ", i);
        scanf("%d", &score[i]);
        sum += score[i];
    }

    /* ここにキャストを使った平均計算を書く */

    return 0;
}
答えの例を表示
    double avg = (double)sum / 5;
    printf("平均: %.1f\n", avg);

22-6 理解度チェック

Q1. 次のコードの出力として正しいものはどれか。

int a = 7, b = 2;
double result = a / b;
printf("%.1f\n", result);
解説を表示

正解:イ(3.0)

a / b は整数同士の除算なので結果は 3(切り捨て)。それが double に変換されて 3.0 になる。

Q2. 次のコードの出力として正しいものはどれか。

int a = 7, b = 2;
double result = (double)a / b;
printf("%.1f\n", result);
解説を表示

正解:ア(3.5)

(double)a で a が double になり、b も double に格上げされてから除算 → 3.5。

Q3. int n = (int)3.9; の結果として正しいものはどれか。

解説を表示

正解:イ(3)

実数→整数のキャストは小数点以下を切り捨てる(四捨五入ではない)。

Q4. 次の2つのコードのうち、出力が異なるものについて正しい説明はどれか。

/* A */ double r = (double)(3 / 2);
/* B */ double r = (double)3 / 2;
解説を表示

正解:イ

A:先に整数除算 3/2=1 が行われ、その後 double に変換 → 1.0
B:3 を先に double にキャストしてから 2 と除算 → 1.5