其他注意事项

移植代码时,请考虑以下几点:

  • 以下假设不再有效:

    #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) 生成“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];
    };
    

    以下代码是错误的,因为编译器将使用额外的 4 个字节填充结构,以便进行 8 字节对齐:

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

    以下代码正确:

    malloc(offsetof(struct xx, Pointers) + 100*sizeof(PVOID));
    
  • 不要传递给 (HANDLE)0xFFFFFFFFCreateFileMapping 等函数。 请改用 INVALID_HANDLE_VALUE

  • 打印字符串时,请使用正确的格式说明符。 使用 %p 以十六进制格式打印指针。 这是打印指针的最佳选择。 Microsoft Visual C++支持 %I 打印多态数据。 Visual C++ 还支持 %I64 打印 64 位的值。