その他の考慮事項
コードを移植するときは、次の点を考慮してください。
次の前提条件は有効ではなくなりました。
#ifdef _WIN32 // Win32 code ... #else // Win16 code ... #endif
ただし、64 ビット コンパイラは下位互換性のために_WIN32を定義します。
次の前提条件は有効ではなくなりました。
#ifdef _WIN16 // Win16 code ... #else // Win32 code ... #endif
この場合、else 句は_WIN32または_WIN64を表すことができます。
データ型の配置には注意してください。 TYPE_ALIGNMENT マクロは、データ型の配置要件を返します。 例:
TYPE_ALIGNMENT( KFLOATING_SAVE )
x86 では == 4、Intel Itanium プロセッサTYPE_ALIGNMENT( UCHAR )
では 8 == 1例として、現在次のようなカーネル コードがあります。
ProbeForRead( UserBuffer, UserBufferLength, sizeof(ULONG) );
おそらく次のように変更する必要があります。
ProbeForRead( UserBuffer, UserBufferLength, TYPE_ALIGNMENT(IOCTL_STRUC) );
Intel Itanium システムでは、カーネル モードアラインメント例外の自動修正が無効になります。
NOT 操作には注意してください。 以下、具体例に沿って説明します。
UINT_PTR a; ULONG b; a = a & ~(b - 1);
問題は、~(b–1) が "0xFFFF FFFF xxxx xxxx" ではなく "0x0000 0000 xxxx xxxx" を生成することです。 コンパイラはこれを検出しません。 これを修正するには、次のようにコードを変更します。
a = a & ~((UINT_PTR)b - 1);
署名されていない操作と署名された操作を実行する場合は注意してください。 以下、具体例に沿って説明します。
LONG a; ULONG b; LONG c; a = -10; b = 2; c = a / b;
結果が予期せず大きくなります。 ルールは、いずれかのオペランドが符号なしの場合、結果は符号なしになります。 前の例では、a は符号なし値に変換され、b で除算され、結果は c に格納されています。 変換には、数値操作は必要ありません。
別の例として、次のことを考えてみましょう。
ULONG x; LONG y; LONG *pVar1; LONG *pVar2; pVar2 = pVar1 + y * (x - 1);
この問題は、x が符号なしであるために発生します。これにより、式全体が符号なしになります。 これは、y が負でない限り正常に動作します。 この場合、y は符号なし値に変換され、式は 32 ビットの有効桁数を使用して評価され、スケーリングされ、pVar1 に追加されます。 32 ビット符号なし負の数値は、大きな 64 ビットの正の数になり、間違った結果が得られます。 この問題を解決するには、x を符号付き値として宣言するか、式で LONG に明示的に型キャストします。
小片サイズの割り当てを行うときは注意してください。 次に例を示します。
struct xx { DWORD NumberOfPointers; PVOID Pointers[100]; };
次のコードは間違っています。コンパイラは構造体に追加の 4 バイトを埋め込み、8 バイトのアラインメントを行うためです。
malloc(sizeof(DWORD) + 100*sizeof(PVOID));
次のコードは正しいです。
malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
CreateFileMapping などの関数には渡
(HANDLE)0xFFFFFFFF
さないでください。 代わりに、INVALID_HANDLE_VALUEを使用 します。文字列を印刷するときは、適切な書式指定子を使用します。 %p を使用してポインターを 16 進数で出力します。 これは、ポインターの印刷に最適な選択肢です。 Microsoft Visual C++では、多形データを印刷するための %I がサポートされています。 Visual C++ では、%I64 で 64 ビットの値を出力することもできます。