プログラミング/固定幅整数
コンピュータシステムは、データをビットの列として扱います。このビット列を整数として解釈し、算術演算や論理演算を行うことができます。固定長整数(fixed-width integer)は、あらかじめ決められたビット数の整数型で、主に符号付き整数と符号なし整数に分類されます。この章では、固定長整数の基本概念、符号付きと符号なしの違い、演算時の注意点について解説します。
固定長整数とは
編集固定長整数とは、データのサイズが固定されたビット数(例えば、8ビット、16ビット、32ビット、64ビットなど)で表現される整数型のことです。一般的に、ビット数に応じて表現できる整数の範囲が決まり、ビット数が大きいほど表現できる数も大きくなります。
- 8ビット整数:1バイトの整数。通常、0から255の範囲(符号なしの場合)または-128から127の範囲(符号付きの場合)。
- 16ビット整数:2バイトの整数。通常、0から65535の範囲(符号なしの場合)または-32768から32767の範囲(符号付きの場合)。
- 32ビット整数:4バイトの整数。通常、0から4294967295の範囲(符号なしの場合)または-2147483648から2147483647の範囲(符号付きの場合)。
- 64ビット整数:8バイトの整数。非常に大きな範囲の数値を表現できます。
符号付き整数と符号なし整数
編集固定長整数には、符号付き整数(signed integer)と符号なし整数(unsigned integer)の2種類があります。
- 符号付き整数:数値が正か負かを表現するために最上位ビット(MSB, Most Significant Bit)を符号ビットとして使用します。通常、最上位ビットが0の場合は正の数、1の場合は負の数を表します。例えば、8ビット符号付き整数では、-128から127までの範囲の整数を表現できます。
- 例:8ビット符号付き整数で「11111111」は -1、「00000001」は 1、「10000000」は -128 を表します。
- 符号なし整数:符号なし整数はすべてのビットを数値として解釈し、負の数を持ちません。表現できる範囲はすべて非負の数です。例えば、8ビット符号なし整数では、0から255までの範囲の整数を表現できます。
- 例:8ビット符号なし整数で「11111111」は 255、「00000001」は 1 を表します。
オーバーフローとアンダーフロー
編集固定長整数はビット数が固定されているため、表現できる数には限界があります。演算の結果がその範囲を超えると、オーバーフロー(正の数の範囲を超えた場合)やアンダーフロー(負の数の範囲を超えた場合)が発生します。オーバーフローやアンダーフローが発生した場合、結果は通常の算術演算とは異なる結果になる可能性があります。
- 符号付き整数の場合:
- オーバーフローが発生すると、最小値に巻き戻ります。
- アンダーフローが発生すると、最大値に巻き戻ります。
- 例:8ビット符号付き整数で
127 + 1
を計算すると、結果は-128
になります(オーバーフロー)。
- 符号なし整数の場合:
- オーバーフローが発生すると、最小値に巻き戻ります。
- 例:8ビット符号なし整数で
255 + 1
を計算すると、結果は0
になります(オーバーフロー)。
ビット操作
編集固定長整数は、ビットレベルでの操作が可能です。主なビット操作には、次のようなものがあります。
- ビット論理演算:AND、OR、XOR、NOT などの論理演算をビット単位で行います。
- AND (
&
):両方のビットが 1 なら 1、それ以外は 0。 - OR (
|
):いずれかのビットが 1 なら 1、それ以外は 0。 - XOR (
^
):一方のビットが 1 で、他方が 0 なら 1、両方が同じなら 0。 - NOT (
~
):各ビットを反転(1 を 0 に、0 を 1 に)。
- AND (
- シフト演算:ビット列を左や右にシフトさせます。
- 左シフト (
<<
):ビット列を左にシフトし、空いたビットに 0 を詰めます。これは 2 のべき乗で掛け算を行うのと同じ効果を持ちます。 - 右シフト (
>>
):ビット列を右にシフトします。符号付き整数の場合、符号ビットが保持されます。符号なし整数では 0 を詰めます。
- 左シフト (
固定長整数の用途
編集固定長整数は、次のような様々な用途で使用されます。
- 低レベルのプログラム:組み込みシステムやハードウェア制御などの低レベルのプログラムでは、メモリや性能の制約が厳しいため、固定長整数が重要です。これらのシステムでは、整数のビット数を最適化してメモリを節約する必要があります。
- 暗号アルゴリズム:固定長整数は、暗号アルゴリズムやハッシュ関数などのビットレベルの演算が必要な場面で広く使用されます。例えば、SHA-256などのハッシュアルゴリズムでは、32ビットや64ビットの固定長整数がビット操作に用いられます。
- ネットワーク通信:ネットワークプロトコルでは、ヘッダーやデータパケットのフィールドが固定長整数で定義されることが多く、特定のビット列がフラグとして解釈される場合があります。
固定長整数のプログラム例
編集以下は、固定長整数を使用した基本的な演算のプログラム例です。
#include <stdio.h> #include <stdint.h> // 固定長整数型を定義するためのヘッダ int main() { // 符号なし8ビット整数 uint8_t a = 200; uint8_t b = 55; uint8_t result = a + b; // オーバーフローに注意 printf("結果: %u\n", result); // 結果は255 // 符号付き32ビット整数 int32_t x = 2147483647; // 32ビット符号付き整数の最大値 int32_t y = 1; int32_t sum = x + y; // オーバーフローが発生 printf("符号付き32ビットの結果: %d\n", sum); // 結果は -2147483648 // ビットシフトの例 uint8_t shift_example = 1; shift_example = shift_example << 3; // 左に3ビットシフト(1 * 2^3 = 8) printf("左シフトの結果: %u\n", shift_example); // 結果は8 return 0; }
まとめ
編集固定長整数は、コンピュータ上で効率的に整数演算を行うための基本的なデータ型です。符号付き整数と符号なし整数の違い、オーバーフローやビット操作について理解しておくことは、低レベルのプログラミングやアルゴリズム実装において重要です。この章で紹介した内容を基礎として、より高度な整数演算やビット操作に進むことができます。