今まで、変数の型は、整数型のint型と、文字型のchar型を扱ってきました。
C言語には、整数値、小数値、扱える値の範囲、符号あり、符号なしなどによって、いろんな型が用意されています。
今回は、変数の型の種類と特徴について学びます。
C言語の基本的なデータ型の種類
C言語では、変数の型の種類は、大きく分けて、3種類あります。
文字型、整数型、浮動小数点型の3種類です。
今まで学んだchar型は、文字型に分類され、int型は、整数型に分類されています。
また、浮動小数点とは、符号部、指数部、仮数部、基数で表現された小数点をいいますが、今は、小数点数を扱う場合は、浮動小数点型を使うということを覚えておけば十分だと思います。
この浮動小数点など、小数点のある値のことを、実数と呼びます。
浮動小数点の符号、指数、仮数、基数について補足します。
- 符号
マイナスかプラスの値かを示すデータです。 - 仮数
小数点数の値から小数点を除いた、または、小数点を移動させたデータです。
例えば、12.3なら、123などの仮の値になります。
次に説明する指数によって、小数点の位置が動くため、仮の値となっています。 - 指数
仮数の値に対して、小数点の位置をどれだけ移動させるかを指定するデータです。 - 基数
各桁の重み付けの基本となる数値です。
10進数や、2進数の、10や2のことです。
次に、C言語で使用できる型の一覧を示します。
種類 | データ型 | サイズ例 | 値の範囲例 |
文字型 | (signed)char | 1バイト | -128~127 |
unsigned char | 1バイト | 0~255 | |
整数型 | (signed) short(int) | 2バイト | -32768~32767 |
unsigned short (int) | 2バイト | 0~65535 | |
(signed) int | 4バイト | -2147483648~2147483647 | |
unsigned int | 4バイト | 0~4294967295 | |
(signed) long (int) | 4バイト | -2147483648~2147483647 | |
unsigned long (int) | 4バイト | 0~4294967295 | |
(signed) long long (int) | 8バイト | -9223372036854775808~9223372036854775807 | |
unsigned long long (int) | 8バイト | 0~18446744073709551615 | |
浮動小数点型 | float | 4バイト | 単精度浮動小数点数 |
double | 8バイト | 倍精度浮動小数点数 | |
long double | 16バイト | 四倍精度浮動小数点数 |
データ型の ( ) で書いているsigned や int は省略可能という意味で付けています。実際は、( )は不要です。
変数の型のことをデータ型と言います。
データ型に記載されている、signedや、unsignedについて、signedは、符号ありを示しています。unsignedは、符号なしを示しています。
このsignedは、省略可能です。このため、signed、unsignedが付いていない場合は、signedが付いているものとして扱われます。
サイズや値の範囲についてですが、例として挙げています、これは、開発環境によってサイズが異なる可能性があるためです。
必ずこのサイズや範囲になるとは限らないので注意が必要です。
使用したいデータの値の範囲や、マイナス値の有無などにより、使用する変数のデータ型を切り分けます。
浮動小数点型は、小数点数を扱いますが、コンピュータは、0と1の2進数というもので計算しているため、誤差が生じることがあります。
例えば、0.1 などは、2進数では表現できないためです。これにより、浮動小数点数を比較するとき、表面上は一致していても、微妙な誤差のせいで、一致しないことが起こります。
データ型に対応した変換指定子は何を使用するのか
今まで、int型は、%dを、char型は、%c、文字列は、%sを変換指定子に使用してきました。
その他のデータ型は、どのような変換指定子を使用すればよいでしょうか。本来なら、変換指定子も細かな書式がありますが、ここでは割愛します。
今は、次のように覚えておいていただければ十分かと思います。
データ型 | 変換指定子 |
char / unsigned char | %c |
short / unsigned short | %d |
int / unsigned int | %d |
long / unsigned long | %ld |
long long / unsigned long long | %lld |
float | %f |
double | %lf |
long double | %Lf |
小数を入力する
小数点の表示は、通常、小数点以下6桁となるように出力されます。
小数を入力するサンプルプログラムを次に示します。
#include <stdio.h>
int main(void)
{
double number;
scanf("%lf", &number);
printf("%fを入力しました。", number);
return 0;
}
printf関数では、double型も%fで使用しますので注意が必要です。ただし、最近では、%lfを使うことも許容されているようです。
実行結果は、次のようになります。
実行結果
1.5 ←入力したデータ
1.500000を入力しました。
このように、小数点以下6桁で表示されていることがわかると思います。
異なる型同士の代入
基本的に、異なる型同士の代入が可能です。小さいサイズの型を大きいサイズの型に代入する場合は、特に問題ありません。しかし、大きいサイズの型を小さいサイズの型に代入する場合、代入する値により、異なる数値が代入されてしまう場合があります。また、小数点数を整数の型に代入すると、小数点以下が切り捨てられてしまいます。このように異なる型の代入は注意が必要です。
異なる型を代入する場合など、注意が必要なサンプルプログラムを次に示します。
#include <stdio.h>
int main(void)
{
char ch1;
int num1, num2;
num1 = 1.5;
num2 = 256;
ch1 = num2;
printf("%d\n", num1);
printf("%d\n", ch1);
return 0;
}
int型のnum1には、小数点数を代入しています。そして、char型のch1には、int型のchar型の範囲より大きい数値を代入しています。
実行結果は次のようになります。
実行結果
1
0
整数型であるint型に小数点数を代入すると、小数点以下が切り捨てられた値が代入されます。
char型に、int型を代入すると、int型の変数の値がchar型の範囲内であれば問題ないのですが、それよりも大きな値が代入されると予期しない値となってしまいます。
異なる型同士の代入ではありませんが、次の計算式の結果にも注意が必要です。
#include <stdio.h>
int main(void)
{
int num1 = 60000;
int num2 = 40000;
int num3 = 200000;
int ans;
ans = (num1* num2) / num3;
printf("%d\n", ans);
return 0;
}
各変数に代入している値は、特に意味はないです。適当に選びました。
ansに代入される計算結果は、12000と出力されることを期待しています。
実行結果は次のようになります。
実行結果
-9474
初期化時に代入した値は、int型の範囲内です。そして、計算結果もint型の範囲内です。ただし、num1 * num2の結果が、int型の範囲を超えてしまい、おかしくなった値に、除算をした結果、実行結果のような値になってしまいました。このように、型が同じでも計算過程で、型の範囲を超えてしまうと、計算結果がおかしくなりますので注意が必要です。
開発環境によって、正しい結果が表示されている場合もあります。
暗黙の型変換
先ほど、小さいサイズの型を大きいサイズの型に代入する場合は、特に問題ないと説明しました。異なる型同士はなぜ代入が可能かというと、代入するときに、代入する先の型に自動的に変換されるからです。このように型が勝手に変換されることを暗黙の型変換といいます。
暗黙の型変換は、代入だけでなく、異なる型どうしで演算する場合にも行われる場合があります。
#include <stdio.h>
int main(void)
{
long long num1 = 60000;
int num2 = 40000;
int num3 = 200000;
int ans;
ans = (num1* num2) / num3;
printf("%d\n", ans);
return 0;
}
先ほどのサンプルプログラムのnum1の型をlong long型に変更したものです。このサンプルプログラムを実行すると、 期待通り、12000と表示されます。
これは、演算を行う場合、一般的に、オペランドの大きなサイズのほうに暗黙の型変換が行われてから演算を行うという決まりになっているためです。
数値の種類
数値を表現するときに、私たちは、通常は、10進数というものを用いています。
これは、0~9の10個の数字で1桁をあらわし、桁が一つ左へ移動すると10倍(10の1乗)に、二つ左へ移動すると100倍(10の2乗)になります。また、右に一つ移動すると、1/10(10の-1乗)に、右に二つ移動すると、1/100(10の-2乗)になります。
そして、プログラミングでは、10進数の他に、8進数、16進数、2進数を扱うことがあります。このため、ここで、これらについて、少し学んでおこうと思います。
- 8進数
0~7の8個の数字で1桁をあらわします。桁が一つ左へ移動すると8倍(8の1乗)に、二つ左へ移動すると64倍(8の2乗)になります。また、右に一つ移動すると、1/8(8の-1乗)に、右に二つ移動すると、1/64(8の-2乗)になります。
プログラムで8進数を扱う場合は、先頭に 0 を付ける必要があります。
例えば、012、030などが8進数です。10進数では、10、24になります。 - 16進数
0~9と、A~Fの16個の数字で1桁をあらわします。桁が一つ左へ移動すると16倍(16の1乗)に、二つ左へ移動すると256倍(16の2乗)になります。また、右に一つ移動すると、1/16(16の-1乗)に、右に二つ移動すると、1/256(16の-2乗)になります。
プログラムで16進数を扱う場合は、先頭に 0x を付ける必要があります。
例えば、0x12、0x30などが16進数です。10進数では、18、48になります。 - 2進数
0~1の2個の数字で1桁をあらわします。桁が一つ左へ移動すると2倍(2の1乗)に、二つ左へ移動すると4倍(2の2乗)になります。また、右に一つ移動すると、1/2(2の-1乗)に、右に二つ移動すると、1/4(2の-2乗)になります。
プログラムで2進数を扱う場合は、先頭に 0b を付ける必要があります。
プログラムでは、2進数で記述することはほとんどありません。
それは、2進数の4桁を16進数の1桁で表現できるからです。
例えば、0b00010001は、16進数では、0x11になります。
以上が、変数の型と数値の種類についてでした。
次は、プログラムの部品化を行う、関数の仕組みについて学びます。