型変換
式内型変換
これまでも、計算式を何度も使ってきましたが
式のオペランドに、当然変数を用いることも多々あります
しかしそれらの変数が必ずしも同じ型であるとは限りません
たとえば計算式の演算でint型とfloat型の演算が行なわれた場合はどうなるでしょう
じつはC言語では、異なる型の演算が可能になっています
これは、厳密に型変換アルゴリズムが定義されているためなのです
Cは式の中でもっともサイズの大きいオペランドに合わせて変換というお約束があるのです
char型などは、式の演算時に一時的にint型に拡張されて変換されます(式の評価時のみ、Java言語と同じ)
このような変換規則を整数拡張(integral promotion)と呼びます
そして、最終的には型変換アルゴリズムをもとにもっとも大きいオペランドに合わせて変換されます
これを型の昇格(type promotion)と呼びます
たとえば、下のプログラムを作成して実行してみてください
#include <stdio.h>
int main()
{
int var1 = 100;
float var2 = 200.123;
printf("%g",var1 + var2);
return 0;
}
このプログラムでは、最終的にfloat型に変換されて出力されます
型変換アルゴリズムをまとめると、以下のような図になります
一方が long double型
| No→
|
一方が double型
| No→
|
一方が float型
| No→
|
一方が unsigned long型
| No→
|
一方が long型
| No→
|
一方が unsigned int型
|
---|
Yes↓ | | Yes↓ | | Yes↓ | | Yes↓ | | Yes↓ | | Yes↓
|
---|
もう一方を long double 型に変換
|
|
もう一方を double型に変換
|
|
もう一方を float型に変換
|
|
もう一方を unsigned long 型に変換
|
|
もう一方を long型に変換
|
|
もう一方を unsigned int 型に変換
|
ただし、long型とunsigned int型の演算で
unsigned int型に格納されている値がlongで表せない場合はunsigned longに変換されます
代入型変換
ひとつの式の内部での型変換は理解できましたね
では、さらにその評価の結果をある変数に代入するときはどうでしょうか?
これも式同様に、必ずしも同じ方の変数に代入されるとは限りませんね
C言語では、代入にも型のちがう場合は変換して代入されます
このとき左辺のサイズが右辺の型より大きい場合は何の問題もありません
#include <stdio.h>
int main()
{
unsigned char var1 = 128;
int var2 = var1;
printf("%d",var2);
return 0;
}
この場合はchar型変数 var1 がint型変数 var2 に問題なく変換され代入されます
char型が文字定数であったも同じことで、そのコードがint型に変換されて代入されます
しかし、逆に左辺の変数型が右辺の評価よりもサイズが小さい時は問題がありますね
この場合でもエラーは発生しません。値はデータを損失して代入されます
損失するという言葉を聞くと、心理的に良い印象は受けませんが実は意外とこれが大切であることもあります
intからcharなどに変換された場合は上位ビット切り捨てで代入されます
たとえば以下のプログラムを考えましょう
#include <stdio.h>
int main()
{
int var1 = 1279;
unsigned char var2 = var1;
printf("%d",var2);
return 0;
}
unsigned charが格納できるのは255までの整数です。つまり1279という数は表示できません
かなり数学的に勘のいい人は、このプログラムがなにを出力するかわかったでしょう
正解は 255 を出力します
なぜか、先ほども言いましたがunsigned char型にint型の変数var1が変換される時に上位ビットが切り捨てられています
結果として、下位8ビットが代入されているのです
32ビットの1279は2進数にすると 0000 0000 0000 0000 0000 0100 1111 1111 です
これを上位ビットを切り捨てて8ビットに直すと 1111 1111 つまり10進数で255になるのです
これは、理解した上で意図的に用いると便利です
あるデータの下位8ビットだけを抽出したい場合などはこの方法が用いられます
long doubleからdoubleなどの変換は、精度が落ちます
また、浮動小数点型から整数型への変換を行なうと小数点以下切り捨てになります
#include <stdio.h>
int main()
{
float var1 = 1234.5678;
int var2 = var1;
printf("%d",var2);
return 0;
}
結果は1234と表示されます
型キャスト
型キャストとは、一時的に変数の型を変換するものです
ある一部分の演算で浮動小数点の小数部を切り捨て、int型として算術したい場合などに有効です
型キャストは評価する値の前にデータ型を指定します
(型) 値
これを用いれば、浮動小数点などに以下のような演算を可能とします
#include <stdio.h>
int main()
{
float var1 = 1234.5678f;
printf("全体 = %f\n",var1);
printf("実数 = %d\n",(int)var1);
printf("小数 = %g\n",var1 - (int)var1);
return 0;
}
型キャストを用いることによって、代入演算などもより柔軟に対応することができます