C言語では異なる型の値が混在するとき、自動または明示的に型変換が行われる。
意図しない変換はバグの原因になるため、仕組みをきちんと理解しておく。
代入や演算で型が自動的に変換されることを暗黙的型変換(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
最も起きやすいバグが「整数同士で割り算してから double に代入する」パターン。
#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 にはならない。
意図的に型を変換することを明示的型変換(explicit conversion)またはキャストという。
(変換後の型) 値
#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)(a / b) と書くと整数除算した後に変換するため 1.0 になる。| コード | 計算の流れ | 結果 |
|---|---|---|
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 |
次のコードを修正して 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桁で表示するプログラムを作れ。
キャストを使って正確な実数で計算すること。
#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);
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