这是如何工作的?
我从here查看了本教程:
WNDPROC fWndProc =(WNDPROC)GetWindowLong(Msg.hwnd,GWL_WNDPROC);
从msdn开始,它解释了GetWindowLong返回的LONG定义为long。这让我感到困惑,因为它被转换为函数指针(WNDPROC)。
将long转换为函数指针会发生什么?它们是完全不同的东西。当长期不是函数时,函数指针如何工作?
答案 0 :(得分:3)
指针只是变量的地址;所以它由整数表示。
标准说uintptr_t
和intptr_t
与指针
#include <stdint.h>
int a;
int *pa = &a;
uintptr_t addr_of_a = (uintpt_t)pa;
在32位系统中,sizeof(uintptr_t)
= sizeof(int *)
= 4
。在64位系统中,他们需要8
。
GetWindowLong
函数用于32位系统,因此其返回值类型为LONG
,即4字节。
然而,在64位系统中,指针的大小为8字节。所以microsoft弃用GetWindowLong
,你应该使用GetWindowLongPtr
和LONG_PTR
。
// the type of the return value of GetWindowLongPtr is LONG_PTR. So this code is safe and portable.
WNDPROC fWndProc = (WNDPROC)GetWindowLongPtr(Msg.hwnd, GWLP_WNDPROC);
答案 1 :(得分:1)
在32位Windows上, LONG 是32位值,与地址大小相同。 @Chris是对的,它作为一个函数指针开始转换为long,然后将它作为函数指针进行类型转换。
如果您查看来自MSDN的说明,您会注意到GetWindowLongPtr()
已取代原始呼叫。它返回 LONG_PTR ,这是Microsoft声明一个与当前流程体系结构上的指针大小相同的long的方式。基本上,它将是32位地址,32位进程,但64位进程为64位。
答案 2 :(得分:1)
它假设您正在一个系统上运行,在该系统中,函数的所有可能地址之间存在双射,以及long的所有非陷阱表示的子集。
换句话说,只要存在至少与WNDPROC值一样多的LONG值,那么这可以起作用。
通常,编译器只会将WNDPROC中的位铲到GetWindowLong中的LONG的内存(或寄存器)中,然后将它们铲回到WNDPROC中以显示您所在的行。