C ユーザーズガイド

単一ソースコードの実現

この節では、32 ビットと 64 ビットの両方でコンパイル可能な単一ソースコードの作成に使用できる資源をいくつか紹介します。

派生型

32 ビットと 64 ビットのどちらのコンパイル環境でも安全なコードにするには、システム派生型を使用します。一般的に、変更の可能性がある場合には派生型を使用することをお勧めします。派生データ型を使用すると、データ型モデルの変更あるいは移植に際して、システム派生型を変更すればよいだけになります。

システムインクルードファイルの <sys/type.h> および <inttypes.h> には、32 ビットと 64 ビットのどちらにも安全なアプリケーションの作成に役立つ定数、マクロ、派生型が含まれています。

<sys/types.h>

アプリケーションのソースファイルに <sys/types.h> をインクルードして、_LP64 および _ILP32 の定義を使用できるようにしてください。このヘッダーには、必要に応じて使用される基本派生型もいくつか含まれています。特に次は大切です。

これらの派生型はすべて、ILP32 コンパイル環境では 32 ビット量のままですが、LP64 コンパイル環境では、64 ビット量になります。

<inttypes.h>

<inttypes.h> インクルードファイルには、コンパイル環境に関係なく、明示的にサイズ指定されたデータ項目との互換性を持たせるのに役立つ定数、マクロ、派生型が含まれています。このファイルには、8、16、32、64 ビットオブジェクトを操作するための仕組みも含まれています。<inttypes.h> は ANSI C 提案の一部であり、ISO C 規格 (ISO/IEC 9899:1990 プログラミング言語 C) の改訂に備えて ISO、JTC1、SC22、WG14 C 委員会が策定中の草案の一部を残しています。<inttypes.h> に含まれることが議論されている基本機能としては、次があります。

次に <inttypes.h> のこれらの基本機能について詳しく説明します。

固定幅の整数型

<inttypes.h> が提供する固定幅の整数型には、int8_tint_16tint32_tint64_t などの符号付き整数型と、uint8_tuint_16tuint32_tuint64_t などの符号なし整数型があります。

指定数のビットを保持できる最小サイズの整数型として定義されている派生型としては、int_least8_t、int_least16_t、int_least32_tint_least64_tuint_least8_tuint_least16_tuint_least32_tuint_least64_t などがあります。

ループカウンタやファイル記述子などの演算に整数を使用することは問題ありません。配列インデックスにロング整数を使用することも問題ありません。しかし、これらの固定幅型はむやみに使用しないでください。固定幅の型は、次の明示的なバイナリ表現に使用してください。

uninptr_t などの便利な型

<inttypes.h> ファイルには、ポインタを保持するのに十分な大きさの符号付き整数型と符号なし整数型 intptr_tuintptr_t が含まれます。また、符号付きと符号なし整数型の中で最長 (ビット) の整数型である intmax_tuintmax_t も提供します。

unitptr_t 型は、unsigned long などの基本型ではなく、ポインタ用の整数型として使用してください。ILP32 と LP64 コンパイル環境で unsigned longpointer が同じサイズであるとしても、uintptr_t を使用するということは、データ型モデルが変わった場合に、その影響を受けるのは uintptr_t の定義だけになることを意味します。このため、他の多くのシステムにコードを移植できるようになります。また、これは、C で自分の意図していることをより明確に表現する手段になります。

intptr_t および uintptr_t 型は、アドレス演算でポインタの型変換を行うときに大変役立ちます。この目的には、longunsigned long ではなく、intptr_tuintptr_t 型を使用してください。

定数マクロ

定数のサイズと符号の指定には、INT8_C(c)INT64_C(c)UINT8_C(c)UINT64_C(c) マクロを使用してください。基本的に、これらのマクロは、必要に応じて定数の末尾に l、ul、ll、ull という文字列を付加します。たとえば、INT64_C(l) は、ILP32 では、定数 1 に ll、LP 64 では l を付加します。

定数を最大型にするときは、INTMAX_C(c)UINTMAX_C(c) を使用してください。これらのマクロは、「LP64 データ型モデルへの変換」で説明している定数型を指定する際に大変役立ちます。

制限値

<inttypes.h> で定義されている上下制限は、いろいろな整数型の最小値と最大値を指示する定数です。これには、INT8_MININT64_MININT8_MAXINT64_MAX などの固定幅型をそれぞれの符合なし型に対する最小値と最大値が含まれます。

<inttypes.h> ファイルには、最小サイズのそれぞれの型に対する最小値と最大値も含まれます。これには、INT_LEAST8_MININT_LEAST64_MININT_LEAST8_MAXINT_LEAST64_MAX 型やこれらに対応する符号なし型があります。

また、<inttypes.h> には、サポートされる最大整数型の最小値と最大値も定義されています。これには、INTMAX_MININTMAX_MAX、これらに対応する符号なし型があります。

書式文字列マクロ

<inttypes.h> ファイルには、printf(3S) および scanf(3S) の書式指示子を指定するマクロも含まれています。基本的にこれらのマクロは、引数のビット数がマクロ名に組み込まれていることを条件に、書式指示子の前に l または ll を付加して、引数が long または long long のどちらであるかを示します。

次の例に示すように、最小および最大整数型を 10 進、8 進、符号なし、16 進の形式で表示する、printf(3S) 用のマクロがあります。


int64_t i;
printf("i =%" PRIx64 "¥n", i);

同様に、最小および最大整数型を 10 進、8 進、符号なし、16 進の形式で読み取る、scanf(3S) 用のマクロがあります。


uint64_t u;
scanf("%" SCNu64 "¥n", &u);

これらのマクロはむやみに使用しないでください。「固定幅の整数型」で説明したように、固定幅型に対して使用することが最も適しています。

ツール

バージョン 5.0 の Sun WorkShop には、64 ビット環境でエラーになりそうな問題を検出する機能拡張版の lint プログラムが付属しています。また、C コンパイラに -v オプションを使用すると、より厳密な意味検査も行われます。-v オプションは、指定されたファイルに対して lint に似た検査もいくつか行います。

64 ビット環境で安全なコードにするには、Solaris 7 オペレーティングシステムに含まれているヘッダーファイルを使用してください。このヘッダーファイルには、64 ビットコンパイル環境用の派生型とデータ構造体の正しい定義が含まれています。

lint

32 ビットおよび 64 ビット両方のコンパイル環境用に作成したコードの検査には、lint を使用してください。LP64 の警告を生成するには、-errchk=longptr64 オプションを使用します。また、ロング整数とポインタのサイズが 64 ビットで普通の整数のサイズが 32 ビットの環境への移植性を検査する場合も -errchk=longptr64 フラグを使用してください。-errchk=longptr64 フラグは、明示的な型変換が使用されているときにも、ポインタ式とロング整数式の普通の整数への代入を検査します。

64 ビットコンパイル環境でだけ実行するコードを検査する場合は、lint-Xarch=v9 オプションを使用してください。

警告する場合、lint は問題のコードの行番号とその問題の内容や、ポインタが関連するかどうかを示すメッセージを表示します。また、関係するデータ型のサイズも示します。ポインタが関係していること、データ型のサイズがわかれば、64 ビットの問題を特定し、32 ビットとそれより小さい型の間に以前から存在している問題を避けることできます。

ただし、64 ビット環境でエラーになる可能性のある問題について警告を出すといっても、lint によってすべての問題が検出できるわけではありません。多くの場合、意図したとおりであり、正しいコードであっても、警告は出されます。

行の前に /*LINTED*/ の形式のコメントを挿入すると、特定の行に対する警告を抑止できます。この機能は、リンクや型変換や代入などの行を無視させる場合に役立ちます。ただし、現実には存在する問題が隠される可能性があるため、/*LINTED*/ コメントを使用するときは、細心の注意を払ってください。詳細は、lint(1) のマニュアルページを参照してください。