その他の考慮事項

コードを移植するときは、次の点を考慮してください。

  • 次の前提は無効です。

    #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 ) == 4 on x86, 8 on Intel Itanium processorTYPE_ALIGNMENT( UCHAR ) == 1 everywhere

    例として、現在次のようなカーネル コードがあります。

    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) によって "0x0000 0000 xxxx xxxx" が生成され、"0xFFFF FFFF xxxx xxxx" が生成されないことです。 コンパイラはこれを検出しません。 これを修正するには、次のようにコードを変更します。

    a = a & ~((UINT_PTR)b - 1);
    
  • 署名されていない操作と署名付き操作を実行する場合は注意してください。 以下、具体例に沿って説明します。

    LONG a;
    ULONG b;
    LONG c;
    
    a = -10;
    b = 2;
    c = a / b;
    

    結果が予期せず大きくなります。 ルールは、いずれかのオペランドが符号なしの場合、結果は符号なしになります。 前の例では、 は符号なし値に変換され、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];
    };
    

    次のコードは間違っています。これは、8 バイトのアラインメントを行うために、コンパイラによって構造体に追加の 4 バイトが埋め込まれるためです。

    malloc(sizeof(DWORD) + 100*sizeof(PVOID));
    

    次のコードは正しいです。

    malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
    
  • CreateFileMapping などの関数には渡(HANDLE)0xFFFFFFFFさないでください。 代わりに、 INVALID_HANDLE_VALUEを使用します。

  • 文字列を印刷するときは、適切な書式指定子を使用します。 ポインターを 16 進数で出力するには、%p を使用します。 これは、ポインターの印刷に最適な選択肢です。 Microsoft Visual C++では、多形データを印刷するための %I がサポートされています。 Visual C++ では、%I64 もサポートされ、64 ビットの値が出力されます。