型変換はいかに操作されるか?

コンパイラは割り当てが実行されるとき、自動型変換が用意されています。 もし、変換先が変換元を表すことができないときは、変換元の情報が失われます。例えば:int8var = int16var;では int16varの上位バイトが失われます。

小さな符号付き変数を大きな符号付き変数に変換するときは、符号は保持されます。例えば、 8ビット符号付き変数が−1のとき、16ビット符号付き変数に-1に変換されます。

負数の符号付きの数を符号無しに変換するときは、2の補数値になります。 例えば、−1を8ビット符号無し(int8)変換すると、255となります。この場合には、符号拡張されません(多ビットへの変換の前に、符号無しに変換されます)。これにより、8ビット符号付きの−1を16ビット符号無しに変換すると、255になることを意味します。

同様に、大きな符号無し数を同一サイズ又は小さなサイズ変換すると正しい値が得られません。例えば、255(符号無し)を8ビット符号有りに変換すると結果は−1になります。

また、上記の変換ルールは関数に渡すパラメータにも適応されます。

バイナリー演算子は違ったタイプのオペランドを持っていますので、下位順位のオペランドは上記のルールにより上位に変換されます。順位は下記の通りです。:

  • Float 浮動少数
  • Signed 32 bit 符号付 32ビット
  • Signed 16 bit 符号付 16ビット
  • 1 bit 1ビット
  • Unsigned 32 bit 符号なし 32ビット
  • Unsigned 16 bit 符号なし 16ビット
  • Signed 8 bit 符号付 8ビット
  • Unsigned 8 bit 符号なし 8ビット

結果はオペランドと同じになります。式での各演算子は別々に評価されます。例えば:

	i32 = i16 - (i8 + i8)

+演算子は8ビットですので、結果は加算の後に16ビットに変換され、そして、− は16ビットです。 その結果は32ビットに変換されます。 もし、i8が200とi16が400だとしますと、i32での結果は256(200+200は8ビットなので結果は144、400−144=256)となります。

変換を行うことを明示するために(type)を挿入することで確実な変換を行う事ができます。例えば、上記の計算は下記のようにi8に(long)を付けることで達成されます。:

	i32 = i16 - ((long)i8 + i8)

この場合は、1番目の i8は16ビットに変換され、そして、加算は16ビットで行われるため、2番目の i8 は16ビットに変換されます。

Cプログラミングにおける類似の誤りとして以下のものがあります:

	i16 = i8 * 100;

これは下記のようにすることで正しい結果が得られます:

	i16 = (long) i8 * 100;

符号無しint(このコンパイラではデフォルト)では、値は決して負にはならないことを覚えておいて下さい。例えば、2-4は254(8ビットで)です。例えば以下の例では、変数 i は決して0以下にはならないので、以下のコードは無限ループになります。:

	int i;
	for( i=100; i>=0; i--)