前回はプロジェクト「0130_suuti_naibu」を新しく作り、char や int などの整数を扱う型について、使われているメモリサイズやビット、バイトでもてる数値の範囲についてキホンを話ししました。
今回は、新しくプロジェクト「0140_implicitconversion」を作り、暗黙の型変換についてお話します。この機能を知っていることで、C言語で計算をしたときにどのような型が内部で使われているのかを理解することができます。今回はさらっと概要のみお話しようと思います。
型キャストを使ったソースコードをビルドして実際にプログラムを動かして結果を見てみましょう。
#include <stdio.h>
#include <limits.h>
int main() {
unsigned char small;
unsigned int big = 257;
float progress = 12.3456f;
printf( "char 型のサイズは 1 バイトで、代入できる最大値は %d \n"
, CHAR_MAX );
printf( "int 型のサイズは %d バイトで、代入できる最大値は %d \n"
, sizeof(int), INT_MAX );
// unsigned int から unsigned char への型キャスト
small = (unsigned char)big;
// 結果表示
printf("small に収まる 1 バイトを big からキャストした結果、small は %d\n", small);
printf("progress の実数部分は %d\n", (int)progress);
printf("progress の小数部分は %f\n", progress - (int)progress);
}
コピペなりして、実行してみて下さい。
char 型の持てる最大値は 127 で、サイズは 1 バイト
int 型の持てる最大値は 2147483647 で、サイズは 4 バイト
char 型に収まるバイトだけとった結果 = 1
progress の実数部分は 12
progress の小数部分は 0.345600
こんな結果になりました。
C言語で最初から扱えるそれぞれの整数型(char型、short型、int型、long型など)について、型が違っていても計算ができます。また、別の型への代入もすることができます。
// char 型に short 型変数を代入し、降格が発生
c = s;
printf("char型変数 c には %d が代入されています。\n", c);
ここでは 1バイトのサイズしかもたない char 型の変数 c に、より 2 バイトのサイズの short 型の変数の中身を代入しています。
前のページで char や short 型のメモリ上のサイズや、変数として持てる数値の幅をお話しましたが、short 型は -32768 ~ 32767、char 型は -128 ~ 127 を持つことができます。
7行目では short 型変数の s にはいっている 100 を、より小さいサイズの char 型に代入しています。
このように、大きい数値をもつことのできる型の数値を、小さい型に代入するときに 格(ランク)の「降格」と呼ばれる処理が行われます。
short から char に降格するとき、char 型の範囲内に収まっていれば、そのまま代入ができます。今回のソースコードでも代入できていますね。
もし数値が大きすぎて char の幅に入りきらないときはどうなるでしょうか。
例えばプログラムを変えて「short s = 200;」 とし、200 を char 型に入れようとすると、「-56」という結果になります。これは char型のもつことのできる範囲である -128~127 にデータが収まらなかったため、収まらなかった分んのビット数の情報が失われてしまってこのようなことになっています。
逆に、char 型で定義した変数の数値(例えば 10 とか)を、short や int 型に代入するときは、問題なくそのまま 10 という数値で代入できます。
char 型よりも short 型や int 型のほうが持てる幅(ビット数)が大きいので、そのままデータを新しい型にコピーできるということです。
このように、char型で定義した数値を short や int 型などの、より大きいサイズの型に変換するとき型の格(ランク)が「昇格」した、と表現します。
いろいろとお話しましたが、実際にプログラムを書くときに、int 型などの大きいサイズのデータ char 型など、より小さなサイズの型に代入しようとすると、注意しないとバグの原因になるということです。
10行目から、12行目では、 char 型、short 型、 int 型が使うバイト数を調べています。
sizeof 演算子については前回お話しているので、よろしければ確認してみてください。
printf("char 型のサイズは %d バイト\n", sizeof(c));
printf("short 型のサイズは %d バイト\n", sizeof(s));
printf("int 型のサイズは %d バイト\n", sizeof(i));
ここで、書いている人のPCでの結果はこのようになっています。 環境によって short や int の結果は変わる可能性があります。
sizeof 演算子の char, short, int 型の結果
型名 | サイズ(バイト) |
---|---|
char | 1 |
short | 2 |
int | 4 |
続いて、ソースコードの14~16行目で掛け算や足し算などの演算を行った結果のサイズを見てみましょう。
// いろいろな型と型の計算結果は int 型になる。
printf("char + char の結果は %d バイト\n", sizeof(c + c));
printf("char * short の結果は %d バイト\n", sizeof(c * s));
printf("short + int の結果は %d バイト\n", sizeof(s + i));
実行すると、すべて 「4 バイト」(つまり int型と同じサイズ)で表示されたかと思います。
このことからもわかるように、int 型より小さい(ランクが低い)サイズをもつ char や short などを組み合わせ計算しても、 内部的には一度 int 型に昇格して計算しているようです。
昇格したり降格したりするのも、CPUの計算が必要ですので、速度面を期待して、charやshort を使うのは意味がないかもしれません。
今回はここまで。お疲れさまでした。
C11 – N1570 を見てみると、変数の型のランクの高低で以下のようなルールが記載されれているようです。備忘も含めて書いておきます。
今回はここまで。お疲れさまでした。
更新日 | 更新内容 |
---|---|
2018/7/16 | ページ初版公開 |
2018/9/8 | アイキャッチ画像、トップ画像を追加 |
コメント、ありがとうございます。
ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。
Twitter:@NodachiSoft_jpお名前:以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください
お名前: