32 ビットおよび 64 ビットコンパイルをサポートする単一ソースコードを書く際に役立つ、アプリケーション開発者向けの資源について説明します。
システム派生型は、コードを 32 ビットおよび 64 ビット安全にするのに便利です。これは、派生型自身が ILP32 および LP64 のデータ型モデルに対して安全であるからです。一般に、変更を可能にするために派生型を使用しておくと便利です。後でデータ型モデルが変更された場合に、または異なるプラットフォームに移植する場合に、アプリケーションそのものではなく、システム派生型を変更するだけで済みます。
システムインクルードファイルの <sys/types.h> と <inttypes.h> には、アプリケーションを 32 ビットおよび 64 ビット安全にするために使用できる定数、マクロ、および派生型が格納されています。これらについての詳細は、このマニュアルでは説明していませんが、一部についてはこの章の以降の節および付録 A 「派生型の変更」 で説明しています。
<sys/types.h>
<sys/types.h> をインクルードするアプリケーションのソースファイルでは、<sys/isa_defs.h> をインクルードすることによってプログラミングモデルシンボル _LP64
と _ILP32
の定義を利用できるようになります。このヘッダーには、それぞれ必要に応じて適切な箇所で使用する基本派生型が多数含まれています。特に次のものは重要です。
clock_t
システムクロック時間を表わします。
dev_t
デバイス番号に使用される型です。
off_t
ファイルサイズとオフセット用に使用される型です。
ptrdiff_t
2 つのポインタの減算結果を示す符号付き整数型です。
size_t
メモリー内のオブジェクトのサイズ (バイト単位) 用に使用される型です。
ssize_t
バイト数またはエラーを返す関数によって使用される「符号付きサイズ」型です。
time_t
秒単位の時間用に使用される型です。
これらの型はすべて、ILP32 コンパイル環境では 32 ビット、LP64 コンパイル環境では 64 ビットになります。
これらの型のいくつかの使用方法については、「LP64 への変換のためのガイドライン」で詳しく説明しています。
<inttypes.h>
インクルードファイルの <inttypes.h> は、定数、マクロ、および派生型を定義するために Solaris 2.6 に追加されました。これによって、明示的にサイズを指定されたデータ項目について、コンパイル環境とは無関係にコードに互換性を持たせることができます。<inttypes.h> は、8 ビット、16 ビット、32 ビット、および 64 ビットのオブジェクトを操作するための機構が含まれてます。このインクルードファイルは、ANSI C の原案の一部で、ISO/JTC1/SC22/WG14 C 委員会による現在の ISO C 標準、つまり ISO/IEC 9899:1990 プログラミング言語 - C の改訂案を反映しています。
<inttypes.h> の主な機能は、次のとおりです。
固定幅整数型の集合
uintptr_t
とその他の有用なデータ型
定数マクロ
制限値
書式文字列マクロ
これらについては以降の節で説明します。
<inttypes.h> で提供される固定幅整数型には、int8_t、 int16_t、 int32_t、 int64_t、 uint8_t、 uint16_t、 uint32_t、 および uint64_t のような、符号付きおよび符号なし整数型があります。特定のビット数を格納できる最小の整数型として定義される派生型には、 int_least8_t、 int_least16_t、 int_least32_t、 int_least64_t、 uint_least8_t、 uint_least16_t、 uint_least32_t、 uint_least64_t があります。
これらの固定幅型を無制限に使用しないでください。たとえば、int
はこれまでと同様に、ループカウンタやファイル記述子などについて使用でき、long
は配列のインデックスに使用できます。固定幅型は、次に示すような明示的なバイナリ表現に使用してください。
ディスク上のデータ
送受信データ
ハードウェアレジスタ
バイナリインタフェース仕様 (明示的にサイズの決められたオブジェクトがあるもの、または 32 ビットプログラムと 64 ビットプログラム間での共有や通信を含むもの)
バイナリデータ構造 (32 ビットプログラムおよび 64 ビットプログラムが、共用メモリー、共用ファイルなどを介して使用するもの)
uintptr_t
とその他の有用なデータ型
<inttypes.h> によって提供されるその他の型として、ポインタを格納するために十分な領域が確保できる符号付きおよび符号なし整数型があります。これらの型には、intptr_t
と uintptr_t
があります。さらに、intmax_t
および uintmax_t
という (ビット単位で) 最長の符号付きおよび符号なしデータ型があります。
uintptr_t
型をポインタ用の整数型として使用する方が、unsigned long
のような基本データ型を使用するよりも便利です。unsigned long
は、IPL32 と LP64 データ型モデルの両方でポインタと同じサイズですが、uintptr_t
を使用すると、uintptr_t
の定義を変更するだけで異なるデータ型モデルを使用できます。このため、他の多くのシステムに移植が可能となります。またこれによって、C プログラムコード中に意図する処理をより明確に記述することができます。
intptr_t
と uintptr_t
型は、アドレス計算をする際にポインタをキャストするのに非常に役に立ちます。long
または unsigned long
の代わりにこれらを使用することができます。
通常は、uintptr_t
を使用してキャストする方が、intptr_t
を使用するよりも安全です。特に比較の場合はこの方法が安全です。
マクロは、定数のサイズと符号を指定するために使用できます。マクロには、INT8_C(c)、INT16_C(C)、INT32_C(C)、INT64_C(c)、UINT8_C(c)、 UINT16_C(C)、UINT32_C(C)、UINT64_C(C) があります。基本的にこれらのマクロは、必要な場合に定数の後に l、ul、ll、または ull を置きます。たとえば、INT64_C(1) は、定数 1 の後に ILP32 の場合には ll を、LP64 の場合には l を付加します。
定数を最大のデータ型にするためのマクロには、INTMAX_C(c) と UINTMAX_C(c) があります。これらのマクロは、「LP64 への変換のためのガイドライン」で説明している定数の型を指定するのに非常に役に立ちます。
<inttypes.h> に定義されている制限値は、さまざまな整数型の最小値および最大値を指定する定数です。これには、INT8_MIN、INT16_MIN、INT32_MIN、 INT64_MIN、INT8_MAX、INT16_MAX、INT32_MAX、INT64_MAX、およびそれらの符号なしの場合のものなど、各固定幅型の最小値と最大値が指定されています。
最小サイズ型のそれぞれの最小値と最大値も指定されています。これらには、 INT_LEAST8_MIN、 INT_LEAST16_MIN、 INT_LEAST32_MIN、 INT_LEAST64_MIN、 INT_LEAST8_MAX、 INT_LEAST16_MAX、 INT_LEAST32_MAX、 INT_LEAST64_MAX、 およびそれらの符号なしのものなどがあります。
サポートされている整数型のうちの最大の型の最小値と最大値も定義されています。これらには、INTMAX_MIN と INTMAX_MAX、およびそれらの符号なしのものがあります。
書式指示子 printf と scanf を指定するためのマクロも <inttypes.h> にあります。これらのマクロは、引数のビット数がマクロ名に組み込まれている場合に、初期指示子の先頭に l または ll を付加することによって引数を long
または long long
として指定します。
printf(3S) 書式指示子用のマクロは、10 進、8 進、符号なし、16 進の、8 ビット、16 ビット、32 ビット、64 ビットの整数、最小整数型と最大整数型を出力するためのものです。64 ビットの整数を 16 進表記で出力する例を、次に示します。
int64_t i; printf("i =%" PRIx64 "¥n", i); |
同様に、scanf(3S) 書式指示子用のマクロが、10 進、8 進、符号なし、および 16 進の 8 ビット、16 ビット、32 ビット、64 ビットの整数、ならびに最小整数型と最大整数型の読み込み用に提供されています。符号なし 64 ビットの 10 進整数を読み込む例を、次に示します。
uint64_t u; scanf("%" SCNu64 "¥n", &u); |
これらのマクロは、無制限に使用しないでください。これらは固定幅型と一緒に使用するのが最適な使用方法です。詳細は、「固定幅整数型」 を参照してください。