2010-06-19 90 views
3

我来到翻过一个代码段,用于检测应用是否在X32仿真环境中运行的x64 PC上 here指向函数的指针和指向WINAPI函数的指针有什么区别?

一般来说,我明白的代码,但有一件事我不明白:

1)的typedef BOOL (WINAPI * LPFN_ISWOW64PROCESS)(HANDLE,PBOOL);

为什么WINAPI必须在那里?为什么知道指针不指向我定义的函数而是指向WINAPI函数非常重要?这两个指针会不一样? (大小的方式,将他们创建等)

感谢,

克拉

回答

4

WINAPI扩展为__stdcall(在大多数情况下 - 您不应该特别依赖该调用约定),这是与默认__cdecl不同的调用约定。不同的是,在__stdcall中,调用的函数清除堆栈,而在__cdecl中,调用者清除堆栈。 __stdcall不支持像__cdecl那样的可变参数长度函数,但__stdcall在某些情况下可以更快并且减少代码大小。

+0

因此,简而言之,WINAPI说编译器在函数完成后不生成代码来清理栈上的乱码? – Kra 2010-06-19 07:01:39

+0

@Kra:大部分,是的。我不知道如何转换成x86_64,但x86的情况绝对如此。 – 2010-06-19 07:20:48

+0

很酷,它是有道理的,当WINAPI被删除时,编译器不会呻吟,并且该应用程序崩溃与信息,ESP值没有正确保存在函数调用。感谢您分享您的知识:) – Kra 2010-06-19 07:31:45

1

WINAPI宏观通常包含与WinAPI的功能实现特定的声明细节。就像一个调用约定。上述指针可以指向任何函数,只要它遵循与WinAPI函数相同的调用约定。

这个宏拼写为WINAPI的事实没有任何意义。它可能拼写为AHELLO_WORLD或其他。这个宏的全部和唯一一点是提供一个地方,其中描述了所有这些WinAPI特定的约定,以便万一发生了某些变化,您只需要在一个地方修改它。

它可能很容易成为一个无法解决的宏。

0

同意以前的帖子。 顺便说一句我真的不明白为什么__cdecl仍然被认为是C/C++的“默认”调用约定。

很显然,使用__cdecl的结果是比__stdcall略大一点的代码,因为该函数只写了一次,通常从几个代码段中调用。是的,__cdecl更灵活,因为它允许可变参数长度。但是,只有用于标记为...的适当功能,才能使用此手机。

例如对于成员函数调用(又名thiscall)Msvc完全是这样的:使用__stdcall -like调用约定,除非该函数接受可变参数。 (另外this通过ECX寄存器传递)。

+0

@valdo:您必须将其与编译器供应商合作。 C++不会说关于调用约定的问题,除了'extern“C”'被允许改变调用约定。 – 2010-06-19 08:03:46