Windows桌面应用程序(1-3-1-5th) 使用指针的规则

将代码移植到32位和64位Microsoft Windows的编译是很简单的。 您只需遵循一些关于转换指针的简单规则,并在代码中使用新的数据类型。 指针操作的规则如下。

  1. 不要将指针强制转换为intlongULONGDWORD
    如果必须转换指针以测试某些位,设置或清除位或以其他方式操作其内容,请使用UINT_PTRINT_PTR类型。 这些类型是整数类型,可扩展为32位和64位Windows的指针大小(例如,对于32位Windows为ULONG,对于64位Windows为_int64)。 例如,假设您正在移植以下代码:
    ImageBase=(PVOID)((ULONG)ImageBase|1);
    作为移植过程的一部分,您可以按如下方式更改代码:
    ImageBase=(PVOID)((ULONG_PTR)ImageBase|1);
    在适当的地方使用UINT_PTRINT_PTR(如果你不确定它们是否是必需的,那么使用它们就没有害处)。不要将指针强制转换为ULONGLONGINTUINTDWORD类型。
    请注意,HANDLE被定义为void*,因此将HANDLE值强制转换为ULONG值以测试,设置或清除低2个字节在64位Windows上是错误的。
  2. 使用PtrToLongPtrToUlong函数截断指针。
    如果必须截断指向32位值的指针,请使用PtrToLongPtrToUlong函数(在Basetsd.h中定义)。这些函数在调用期间禁用指针截断警告。
    小心使用这些功能。使用这些函数之一转换指针变量后,请不要再将其用作指针。这些函数截断地址的高32位,这通常是访问最初由指针引用的内存所需的。使用这些函数而不仔细考虑将导致代码变得不健壮。
  3. 在可能编译为64位代码的代码中使用POINTER_32值时要小心。当指针分配给64位代码中的本机指针时,编译器将对指针进行符号扩展,而不是对指针进行零扩展。
  4. 在可能编译为32位代码的代码中使用POINTER_64值时要小心。编译器将使用32位代码对指针进行符号扩展,而不是对指针进行零扩展。
  5. 小心使用OUT参数。
    例如,假设您有一个定义如下的函数:
    void func(OUT PULONG *PointerToUlong);
    请勿按如下方式调用此功能。
ULONG ul;
PULONG lp;
func((PULONG*)&ul);
lp=(PULONG)ul;

而是使用以下调用。

PULONG lp;
func(&lp);

类型转换&ulPULONG*可防止编译器错误,但该函数会将一个64位指针值写入&ul的内存中。此代码适用于32位Windows,但会导致64位Windows上的数据损坏,并且它将是微妙的,难以查找的损坏。本质上说:不要用C代码耍花招 - 直截了当,简单就好了。
6.小心多态接口。
不要创建接受多态数据的DWORD参数的函数。如果数据可以是指针或整数值,请使用UINT_PTR或PVOID类型。

例如,不要创建一个接受键入为DWORD值的异常参数数组的函数。该数组应该是DWORD_PTR值的数组。因此,数组元素可以保存地址或32位整数值。 (一般规则是如果原始类型是DWORD并且它需要是指针宽度,则将其转换为DWORD_PTR值。这就是为什么存在相应的指针精度类型。)如果您的代码使用DWORDULONG或其他32位类型采用多态方式(也就是说,您确实希望参数或结构成员保存地址),使用UINT_PTR代替当前类型。

7.使用新的窗口类函数。

如果您有包含指针的窗口或类私有数据,则您的代码将需要使用以下新函数:

这些功能可以在32位和64位Windows上使用,但在64位Windows上是必需的。现在使用这些函数准备过渡。

此外,您必须使用64位Windows上的新功能访问类私有数据中的指针或句柄。为了帮助您找到这些情况,在64位编译期间,Winuser.h中未定义以下索引:

  • GWL_WNDPROC
  • GWL_HINSTANCE
  • GWL_HWDPARENT
  • GWL_USERDATA

相反,Winuser.h定义了以下新索引:

  • GWLP_WNDPROC
  • GWLP_HINSTANCE
  • GWLP_HWNDPARENT
  • GWLP_USERDATA
  • GWLP_ID

例如,以下代码无法编译:
SetWindowLong(hWnd,GWL_WNDPROC,(LONG)MyWndProc);
它应该改为如下:
SetWindowLongPtr(hWnd,GWLP_WNDPROC,(LONG_PTR)MyWndProc);
设置WNDCLASS结构的cbWndExtra成员时,请确保为指针保留足够的空间。 例如,如果您当前为指针值保留sizeof(DWORD)字节,请保留sizeof(DWORD_PTR)字节。

8.使用FIELD_OFFSET访问所有窗口和类数据。

通常使用硬编码偏移来访问窗口数据。 此技术无法移植到64位Windows。 要使代码可移植,请使用FIELD_OFFSET宏访问窗口和类数据。 不要假设第二个指针的偏移量为4。

9.LPARAMWPARAMLRESULT类型随平台更改大小。

在编译64位代码时,这些类型会扩展为64位,因为它们通常包含指针或整数类型。 请勿将这些值与DWORDULONGUINTINTintlong值混合使用。 检查您如何使用这些类型,并确保不会无意中截断值。


原文链接:Rules for Using Pointers

猜你喜欢

转载自blog.csdn.net/qq_37422196/article/details/81227722
今日推荐