其他注意事项

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

  • 以下假设不再有效:

    #ifdef _WIN32 // Win32 code
        ...
    #else         // Win16 code
        ...
    #endif
    

    但是,64 位编译器定义_WIN32以实现向后兼容性。

  • 以下假设不再有效:

    #ifdef _WIN16 // Win16 code
        ...
    #else         // Win32 code
        ...
    #endif
    

    在这种情况下,else 子句可以表示_WIN32或_WIN64。

  • 请谨慎使用数据类型对齐方式。 TYPE_ALIGNMENT 宏返回数据类型的对齐要求。 例如:在 x86 上 TYPE_ALIGNMENT( KFLOATING_SAVE ) == 4,Intel Itanium 处理器上的 8TYPE_ALIGNMENT( UCHAR ) == 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;
    

    结果意外很大。 规则是,如果任一作数未签名,则结果为 unsigned。 在前面的示例中,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));
    
  • 不要将 (HANDLE)0xFFFFFFFF 传递给 CreateFileMapping等函数。 请改用 INVALID_HANDLE_VALUE

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