汎整数拡張

整数拡張とは



整数拡張(integral promotion)は、C言語およびC++において、整数型の値をより広い範囲を表現できる型に変換する処理です。具体的には、`char`型や`short`型などの整数型を、演算時に`int`型や`unsigned int`型に自動的に変換することを指します。この変換は、暗黙的に行われるため、プログラマーが意識せずに型の不一致によるエラーを回避するのに役立ちます。

格上げと格下げ



整数拡張は、型の「格上げ」と「格下げ」の2つの側面を持ちます。

  • - 格上げ: より多くのビットを持つ、表現範囲の広い型への変換です。例えば、`char`型から`int`型への変換が該当します。
  • - 格下げ: より少ないビットを持つ、表現範囲の狭い型への変換です。例えば、`int`型から`char`型への変換が該当します。

格上げの際には、変換後の値は、以下の条件を満たす場合には元の値が維持されます。

  • - 符号付き型から符号付き型への変換
  • - 符号無し型から符号付き型への変換
  • - 符号付き型から符号無し型への変換で、変換前の値が正の数の場合
  • - 符号無し型から符号無し型への変換

ただし、符号付き型から符号無し型への変換で、変換前の値が負の数の場合には、変換後の値は別の値に変化します。具体的には、元の値に、変換後の型の表現可能な最大値に1を加えた値を足したものが変換後の値となります。

格下げの際には、変換後の型で表現できる範囲に元の値が収まらない場合、情報が欠落したり、処理系に依存した結果となる可能性があります。

変換のルール



C/C++では、式の中で`char`, `short`, `int`などの整数型が混在する場合、これらの型は演算の前に`int`型または`unsigned int`型に変換されます。

  • - もし元の型の全ての値を`int`型で表現できる場合は`int`型に変換されます。
  • - そうでない場合は`unsigned int`型に変換されます。

この規則により、例えば`unsigned char`型同士の演算でも、実際には`int`型に変換されてから演算が行われます。これにより、演算途中で値がオーバーフローするリスクを減らすことができます。



c
unsigned char uc1 = 10;
unsigned char uc2 = 20;

int result = uc1 * uc2; // uc1とuc2はint型に格上げされてから演算される


この例では、`uc1`と`uc2`は`unsigned char`型ですが、掛け算の演算時には`int`型に格上げされます。したがって、演算結果は`int`型になります。

整数拡張の注意点



整数拡張は便利な機能ですが、暗黙的に型変換が行われるため、予期せぬバグの原因となることがあります。

例1



c
int si = -1;
unsigned int ui = 1;

if (si < ui) { // 比較結果は偽になる
// このブロックは実行されない
}


この例では、`si`は`-1`ですが、比較演算の際に`unsigned int`型に変換されます。`-1`を`unsigned int`型に変換すると、非常に大きな正の数になるため、`si < ui`は偽となります。

例2



c
unsigned char uc = 255;
uc++; // ucは0になる


この例では、`uc`をインクリメントすると、`unsigned char`型では表現できない値になるため、オーバーフローが発生し、`uc`の値は`0`になります。これは、`uc++` の演算の過程で、`uc`が `int` 型に昇格して計算された後、`unsigned char` 型に戻される際に値が切り詰められるためです。

他の言語との比較



C/C++以外の言語にも、類似の型昇格ルールが存在します。

  • - Java: `numeric promotion`というルールがあり、整数型のビット数が厳密に定められています。暗黙的な縮小変換はサポートされません。
  • - C#: `type promotion`というルールがあります。符号無し整数型をサポートしますが、暗黙的な縮小変換はサポートしません。また、符号付き整数型と符号無し整数型の比較結果はC/C++と異なり、直感的なものになります。
  • - F#: 暗黙的な型昇格を許さず、異なる型同士の演算には明示的な変換が必要です。

まとめ



整数拡張は、C/C++において整数型の演算を効率的に行うために重要な機能です。しかし、その動作を理解していないと、予期せぬバグを生む可能性があります。そのため、型の変換ルールを正しく理解し、必要に応じて明示的な型変換を行うことが重要です。

また、異なる処理系でコードを動作させる場合には、整数型のビット数や表現範囲が異なる可能性があるため、移植性を考慮したコードを書くことが推奨されます。

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。