型修飾子


より繊細なデータ型

変数の章で、符号付データと符号なしデータの指定が可能であることに触れました
ここでは、このデータ型の用途に応じて、より細かく変数を指定しましょう

C言語にはvoid型を除いて、4つのデータ型がありました
char int float double の四つです

型宣言子の前に、型修飾子を指定することでそのデータ型を用途に応じてきめ細かく指定できます
これまで私たちが使ってきた代表的な型修飾子が unsigned です
これは、その型が符号なしであることを明示的にして正の数の領域を多く確保するものでした

他にも以下のような修飾子があります
signed
unsigned
long
short

longとshortはint型に適応します
shortはint型よりも小さくlongはint型より大きい領域を確保します
int型では処理しきれない大きなデータや、逆に少量のデータで処理できる場合などの用途で使い分けます
確保される領域は正確に定められていません。環境やコンパイラで異なるので注意してください

longはdouble型にも適応します
これもlong int同様にdoubleよりも大きい領域を確保します

もちろん符合なしのshort int型というのも宣言できます
その場合は unsigned short int と記述します
言うまでもありませんが unsigned long intsigned short intsigned long int もあります

C言語では、型修飾子指定時にintを省略することができます
unsigned int , short int , long intはintを省略しても意図どうりのデータ型が宣言できます

unsigned int var;
unsigned var;

上の二つの宣言は、まったく同じことです

代入は、そのままデータ型にあわせて値を代入するだけですが
printf()関数で明示的にデータを出力するには %d だけではうまくいかないことがあります

unsigned = %u
short = %hd
long = %ld
unsigned long = %lu
long double = %Lf

以上の書式を頭に入れておき、以下のプログラムを参照してください
#include <stdio.h>

int main()
{
        short var1 = 32767;
        long var2 = 32768;
        unsigned short var3 = 40000;
        unsigned long var4 = 4294967295;
        long double var5 = 123456.789;

        printf("%hd\n",var1);
        printf("%ld\n",var2);
        printf("%u\n",var3);
        printf("%lu\n",var4);
        printf("%Lf",var5);

        return 0;
}
intの省略記法を用いてます
ただし、型修飾子で割り当てられるデータサイズはコンパイラなどによって異なります


サインフラグ

ここで少し2進数のお勉強です
signedとunsignedで、割り当てられる領域が同じにもかかわらず表現できる正の数の範囲が異なります
これはsignedの場合、負の数を表現できるように符号付になるためですが、その裏事情に少し顔を出しましょう

なぜ符号付になると表現できる数の範囲が変わってしまうのか
それは、2進数がいかにして負の数を表現しているかという部分に秘密があります
ここでは8ビットで考えてみましょう

8ビットで符号付の場合は -127(-128と紹介している本もあるかも)から127までの数を表現できます
8ビットでの127という2進数は 01111111 です。10000000で128だから間違いないですね

ところが128をchar型の変数に代入すると、-128が返されます
最上位ビットが1になった瞬間に正と負の数が入れ代わりました
そうです、2進数は最上位ビットで正と負の数を判断しているのです!
疑わしければWindows標準の関数計算機を用いて10進数で-128を入力して2進数に変換しても良いでしょう

この最上位ビットのことをサインフラグと呼びます
サインフラグが0ならば正、1ならば負の数なのです
ただし、負の数の場合は複雑で、サインフラグを1にすれば正しく表示されるわけではありません

2進数で負の数を表現するには、まずサインフラグ以外の全ビットを逆転(0を1に、1を0に)します
次に逆転した2進数に1加算します
そしてサインフラグを1にするとこで、目的の整数を負の数として表現できるのです

ここで、50という10進数を2進数にして、さらに負の数にしてみましょう
50は2進数で 0011 0010 です。まず、これをサインフラグ以外反転させます
すると 0100 1101 になりますね。さらに1加算してサインフラグも1にすると
11001110 という結果が得られるはずですね。これが-50です

unsignedを指定することによってサインフラグも整数の表現に使えるようにします
だからunsignedを指定することによって、127しか表現できなかったcharが255まで表現できるようになるのです
当然サインフラグがないのだから、負の数は表現できなくなります
以下のプログラムを作って、いろんな数を入力して実験してみましょう
#include <stdio.h>

int main()
{
        signed char var;

        printf("数を入力してください\n");
        scanf("%d",&var);
        printf("結果 = %d",var);

        return 0;
}



前のページへ戻る次のページへ