整数型
整数型(せいすうがた、英: integer type / integral type)は、コンピュータのプログラムなどのデータ型の1つまたは1群であり、整数を取り扱う。コンピュータで扱うもっとも単純な部類のデータ型のひとつである。C言語やJavaなどの多くのプログラミング言語では、整数型は固定長であり、その固定サイズで表現可能な範囲の、整数の有限な部分集合の要素を値とする型である。また多くの言語において、より大きな範囲の整数値を表現可能なデータ型を扱うことができる、標準あるいは第三者によるライブラリが提供されている。
パスカルによる機械式計算機などが数をその処理の対象としていたことを考えれば、計算機械の歴史において、整数を扱うことはコンピュータ以前からの存在である。
種類
[編集]精度
[編集]コンピュータ上で実数を表現するためによく利用されるのは浮動小数点数だが、有限のビット幅で表現される浮動小数点数は、数学や現実世界における実数を正確に表現できない。そのため、コンピュータで扱う実数は誤差を含んだ近似値となる。一方、整数に関しては誤差はない。ただし、有限のビット幅では、表現可能な整数の範囲は限定される。表現可能な範囲を超えてしまうと算術オーバーフローを起こす。
精度に関しては「正確度と精度」の記事も参照。
固定長と可変長
[編集]多くのプログラミング言語における組み込みの整数型は固定長であり、通例、8ビット・16ビット・32ビット・64ビットといった、8の倍数(オクテット)のビット幅を持つ。また、C言語の組み込み整数型は処理系依存となっており、特にint
型やlong
型はプロセッサのレジスタのワード幅などに合わせたサイズがよく用いられる。これらの組み込み型は通例プロセッサの機械語命令に直接対応するデータ型であり、コンピュータ上で高速に扱うことができる。多くの場合、目的に合わせて、いくつかの固定長サイズの整数型がある(後述)。
一方、整数の任意の値を扱うことができる、可変長の整数というものもある。一般にプロセッサが直接扱うことはできないため、多くのプログラミング言語ではライブラリを利用する。言語仕様としてそのようなデータ型が用意されている言語もあり、一部の言語[要説明]では計算結果に応じてシームレスに固定長と切り替わる(プログラマからは隠蔽されている)。大きい数を扱えることから BigNum あるいは整数であることを示す BigInt、日本語では多倍長などといった名前で呼ばれている。任意精度演算の記事も参照のこと。
符号付きと符号無し
[編集]正負両方の整数を表せる符号付き整数型[注 1]と、非負(0または正)の整数だけを表せる符号無し整数型[注 2]とがある。固定長では、符号付き整数型は、負数を表せるかわりに、表せる値の範囲の約半分が負の側に移動する。
符号無し整数は、ビットの並びをそのまま数値として解釈するが、符号付き整数では、負の値の表現方法にいくつか種類が存在する。また、「グレイコード」など、ビットの並びをそのまま数値として解釈するのではない整数の表現法もいくつもある。
長さ
[編集]可変長の整数型は任意の長さとなる。固定長の整数型は、通例処理系の都合によって定義される。従来からあるC言語およびC++の組み込み整数型にはint
のほかにshort
(short int
) とlong
(long int
) があるが、<limits.h>にて表現可能な上下限値が規定されているだけで、short
の長さはint
の長さ以下であればよく、long
の長さはint
の長さ以上であればよい、という緩い規定しかない(符号無し型も同様)。また内部表現も規定されていなかった(大多数の処理系では2の補数表現が採用されているが、C17/C18以前およびC++17以前の規格では規定されていない[1])。しかし時代の変化により、のちのC/C++標準規格ではビット数と内部表現を明確化した型が別途用意されるようになった。C99/C++11 では int64_t
などの固定幅整数型が標準化されている。このような型は特にAPIなど、移植性や相互運用性が重視されるケースで有用であるが、規格ではオプション扱いであり、実際に固定幅整数型を定義(サポート)するかどうかは処理系に委ねられているため、必ずしも利用できるとは限らない[2]。nビット整数型、nバイト整数型といった用語もある。#データモデルも参照。なお、JavaやC#といった後発言語では、最初から各組み込み整数型のビット幅と内部表現を標準仕様によって規定している。C++20では、符号付き整数型が2の補数表現であることが規定された[3]。同様にC23では、符号付き整数型が2の補数表現であることが規定される予定である[4]。
暗号などで1024ビットや2048ビットといった程度の大きさの整数を扱うことがある。プログラムを書くだけであれば汎用的な可変長整数で扱えるが、暗号では通信のスループットやレイテンシ向上のために性能を求める場合もあり、そういう場合にはそのような固定サイズのデータ型を、組み込み型の集合すなわち配列や構造体のような集成体によって表現し、その処理に特化した関数やマクロ等を定義して使うこともある。
バイト (byte) のサイズやワード (word) のサイズ(異なるバイトがあることについては「バイト (情報) 」の記事を参照)が文脈によって明確な場合に限られるが、バイト型・ワード型・ダブルワード型、などという言いかたでも明確に表現できる。なお、ワードのサイズが不明確な場合でも、(具体的なビット数は不明だが)少なくとも「ダブルワード」はワードの倍だということはわかる。
固定小数点
[編集]固定小数点表現は、整数のあるビットとビットの間に固定された小数点があるものとして扱うことによる小数の表現法であり、一般にプログラマが整数演算を適宜組み合わせながら実装する。
文字型
[編集]ASCII文字コード体系では、7ビットですべての文字を表現可能なことから、1文字を1バイトの整数型として扱うことが可能である。英語圏のみに限れば、ASCIIで十分であった。しかし、日本語・中国語・韓国語など、文字種別の多い言語では、1文字を1バイトで表現することは不可能であり、1文字を複数バイトで表す符号化方式(マルチバイトエンコーディング)が言語ごとに考案された。さらに国際化対応の観点から、言語別の符号化方式ではなく、統一されたユニバーサルな符号化方式としてUnicodeが考案された。Javaは当初、先進的な設計としてUnicode 1.0を取り入れ、char
型をUCS-2を表現する16ビットの型としたが、のちにUnicode 2.0(1996年)で導入されたサロゲートペアのために、1文字にchar
2個を費やす場合が発生することになった。国際化対応の観点からは、Unicodeの異体字セレクタのことなども考慮すれば、"文字"という概念を単純な整数型の一種として扱うのは無謀である。
なおC言語のchar
型については、何があろうと sizeof(char)
が1になる型と、標準で決められている。極端な例としては、メモリのアドレス付けがバイト単位ではなく、16ビットのワード単位のアーキテクチャでも、CHAR_BIT
は16になるが、sizeof(char)
は1で、32ビットのint
は sizeof(int)
が2になる。このように、char
という名前ではあるが「文字型」ではなく、メモリのアドレッシングの最小単位を示す型がchar
である、という役割がある。なお、C/C++のワイド文字型wchar_t
は長さがchar
以上であることが求められているだけであり、エンコーディングに関しても規定はない。
ブーリアン型
[編集]論理演算に使われるブーリアン型は、C/C++では整数型の一種として規定されている。C99で追加された_Bool
型は、サイズは規定されていないが、標準符号無し整数型 (standard unsigned integer type) のひとつである[5]。C++のbool
型は、サイズは規定されておらず、また値としてtrue
またはfalse
のいずれかをとることが標準規格で保証されているが、各種文字型や符号付き・符号無し整数型と併せて、integral type (integer type) と総称されている[6]。
Cでは論理演算式の結果はint
型の1
(真)または0
(偽)となり、もともとブーリアン型は用意されていなかった。そのため、サードパーティ製のライブラリやAPIではコードの意図を明確化するなどの目的で、typedefを使って何らかの組み込み整数型に別名(エイリアス)を与え、独自のブーリアン型(BOOL
やBOOLEAN
など)として定義することがよくあった[7]。
ただしJavaやC#などの後発の言語では、(内部的な表現はともかくとして)言語仕様上は整数型とは独立した別の型として定義されていることも多く、整数型との暗黙的な相互変換(代入)が許可されない。
列挙型
[編集]有限の集合を管理する列挙型は、Cでは整数型の一種である[5]。C++では列挙型は整数型ではなく、そのため従来のスコープ無し列挙型であってもC++11以降のスコープ付き列挙型であっても、列挙型の変数に整数値を暗黙的に代入することはできないようになっているが、汎整数昇格によって、整数型の変数に従来の列挙値を暗黙的に代入することはできる[6]。
Javaの列挙型は参照型(クラス型)の一種であり、整数型ではないが、Enum.ordinal()
によって列挙定数の序数を取得することはできる。C#の列挙型は値型の一種であり、明示的なキャストによって整数型との相互変換が可能である[8]。
ポインタ
[編集]ポインタはメモリアドレスを抽象化した概念だが、ポインタ型と整数型は同一ではない。C言語において、ポインタから整数および整数からポインタへの変換は処理系定義である[9]。C/C++では、2つのポインタ間の減算の結果を格納する符号付き整数型として、ptrdiff_t
が定義されている。C99およびC++11規格ではvoid
へのポインタと相互変換可能な整数型として、intptr_t
およびuintptr_t
が定義されている。
各種コンピュータ言語における標準整数型
[編集]いくつかのコンピュータ言語における標準整数型の対応表を以下に示す。
ビット数 | 符号 | 最小値 | 最大値 | C/C++ (C99, C++11) | C/C++ (ILP32, LLP64) | C/C++ (LP64) | Java | C# | SQL | Go | Rust |
---|---|---|---|---|---|---|---|---|---|---|---|
8 | あり | -(27) | 27 - 1 | int8_t | signed char[注釈 1] | byte | sbyte | tinyint | int8 | i8 | |
なし | 0 | 28 - 1 | uint8_t | unsigned char[注釈 1] | — | byte | unsigned tinyint | uint8 | u8 | ||
16 | あり | -(215) | 215 - 1 | int16_t | short | short | short | smallint | int16 | i16 | |
なし | 0 | 216 - 1 | uint16_t | unsigned short | char | ushort | unsigned smallint | uint16 | u16 | ||
32 | あり | -(231) | 231 - 1 | int32_t | int long | int | int | int | int | int32 int[注釈 2] | i32 isize[注釈 2] |
なし | 0 | 232 - 1 | uint32_t | unsigned int unsigned long | unsigned int | — | uint | unsigned int | uint32 uint[注釈 2] | u32 usize[注釈 2] | |
64 | あり | -(263) | 263 - 1 | int64_t | long long | long long long | long | long | bigint | int64 int[注釈 2] | i64 isize[注釈 2] |
なし | 0 | 264 - 1 | uint64_t | unsigned long long | unsigned long unsigned long long | — | ulong | unsigned bigint | uint64 uint[注釈 2] | u64 usize[注釈 2] | |
128 | あり | -(2127) | 2127 - 1 | — | — | — | — | — | — | — | i128 |
なし | 0 | 2128 - 1 | — | — | — | — | — | — | — | u128 | |
n | あり | -(2n - 1) | 2n - 1 - 1 | — | — | — | — | — | — | — | — |
なし | 0 | 2n - 1 | — | — | — | — | — | — | — | — |
データモデル
[編集]C言語において、ビット数を標準で定めていない型に対する、具体的なビット数の割り当て方をデータモデルという。
特にマイクロプロセッサの64ビット化において、int
とlong
とポインタの扱いが環境によって分かれ、さらに64ビット以上の整数値を表現可能なlong long
型を導入する処理系が増えたことから、それぞれの環境ごとのデータモデルを指す用語が広く使われている。多くの32ビット環境ではint
とlong
とポインタはいずれも32ビットのILP32モデルだったが、Microsoft Windows 64ビット環境ではint
とlong
が32ビットでポインタが64ビット、すなわちIL32P64モデルが使用されている。なおlong long
とポインタが64ビットであることから、LLP64モデルとも呼ばれる。一方、Unix系などの他の64ビット環境ではI32LP64(別名:LP64)モデルが使用されている[10]。また、Crayのようにint
も64ビットであるようなILP64モデルもある。
またその他の例としては、16ビット時代のパーソナルコンピュータ用などで、int
が16ビットということがある。マイコン用などでint
が8ビットというものもあった(ただし、これはC言語標準が要求している値の範囲を満たさない)。GE-600シリーズなどでは1バイトが9ビットのためchar
が9ビットで、整数型は全て36ビットだった(これはC言語規格違反ではない)。
脚注
[編集]注釈
[編集]出典
[編集]- ^ 第6回 整数型の内部表現 | 株式会社きじねこ, Internet Archive
- ^ int8_t - cpprefjp C++日本語リファレンス
- ^ 符号付き整数型が2の補数表現であることを規定 - cpprefjp C++日本語リファレンス
- ^ C23 - cppreference.com
- ^ a b ISO/IEC 9899:yyyy - n2346.pdf
- ^ a b C++ International Standard - n3337.pdf
- ^ Windows Data Types (BaseTsd.h) - Win32 apps | Microsoft Learn
- ^ 列挙型 - C# リファレンス - C# | Microsoft Learn
- ^ INT36-C. ポインタから整数への変換、整数からポインタへの変換
- ^ 64ビットになると何が変わる?――64ビットプログラミングのデータモデル (2/2)