什么 *(DWORD_PTR*)&functionA = functionB( var1, var2);做?
What does *(DWORD_PTR*)&functionA = functionB( var1, var2); do?
*(DWORD_PTR*)&FunctionA = FunctionB( var1, var2, etc...);
这段代码是什么意思?它有什么作用?
我尝试搜索 Google,但我不知道该使用什么术语。
之前的代码中有:
BOOL (WINAPI * FunctionA) (var1, var2, etc...) = NULL;
它标识了 "FunctionA" 是什么。
我假设是 *(DWORD_PTR*)&functionA
部分让您感到困惑?
让我们把它分解成几个部分。让我们从 &functionA
开始。它采用 functionA
的地址(无论是什么)和 return 指向它的指针。
然后我们有 (DWORD_PTR*)
将指向 functionA
的指针转换为指向 DWORD_PTR
的指针。
最后是开头唯一的 *
,它是解引用运算符,它接受一个指针并为您提供 if 指向的值。
和函数调用放在一起,就是简单的把调用functionB
的结果赋值给变量functionA
.
我只是在猜测,但有可能 functionB
return 是一个以某种通用方式指向函数的指针(因为 DWORD_PTR
是我的猜测)然后将其分配给变量 functionA
,该变量可能具有指向函数的类型指针。转换和寻址和取消引用运算符是因为 return 类型 functionB
。 我猜。没有更多信息或上下文,就无法确定。
这是丑陋的代码,就是这样。
它基本上所做的是调用一个函数 (FunctionB
),该函数 return 是指向另一个函数的指针,并将该指针分配给变量 FunctionA
。现在,如果仅此而已,那么代码将看起来非常简单:
FunctionA = FunctionB( var1, var2, etc... );
不幸的是,由于某些奇怪的原因(这可能对最初设计 API 的人来说很有意义),FunctionB
的 return 类型是 not 声明为函数指针,而是 DWORD_PTR
(与底层平台上的指针大小匹配的整数类型)。这意味着 FunctionB
的 return 值不能直接分配给变量 FunctionA
,而必须首先转换为实际的函数指针(正如注释中所指出的那样, 根据 C 标准在技术上是未定义的行为,尽管 POSIX 确实为它定义了语义)。
现在,如果 FunctionA
变量的类型很简单,比如 my_func_ptr_t
,那么这仍然很容易写:
FunctionA = (my_func_ptr_t) FunctionB( var1, var2, etc... );
但是,唉,在你的代码中 FunctionA
声明为:
BOOL (WINAPI * FunctionA) (arg1, arg2, etc...) = NULL;
这意味着它的类型类似于 BOOL (WINAPI *) (arg1, arg2, etc...)
,因此转换看起来像这样:
FunctionA = (BOOL (WINAPI *) (arg1, arg2, etc...)) FunctionB( var1, var2, etc... );
似乎编写该代码的人认为这样的转换太复杂了,而是想出了一个技巧:不是将 FunctionB
的 return 值转换为函数指针,像这样将 FunctionA
转换为 DWORD_PTR
不是更容易吗:
(DWORD_PTR) FunctionA = FunctionB( var1, var2, etc... ); /* this doesn't work :( */
当然,那不会编译;强制转换只是将变量的 value 转换为另一种类型,您不能为转换后的值赋值。 (在技术术语中,a cast is not an lvalue.)但是等等,您 可以 分配给取消引用的指针!所以如果我们...
- 获取指向
FunctionA
的指针(因此将是指向函数指针的指针),
- 将其转换为指向
DWORD_PTR
的指针,并且
- 取消引用该指针,
然后我们得到一个有效的 DWORD_PTR
左值,我们可以分配给它,它恰好与变量 FunctionA
共享相同的内存地址。没关系,根据 C 标准,所有这一切都会以六种方式调用未定义的行为——我们知道我们的编译器会按照我们期望的方式处理它,对吗?
所以,这正是代码的作用:
&FunctionA
returns 指向变量的指针 FunctionA
,
(DWORD_PTR *)
转换此指针,使其现在声称指向 DWORD_PTR
类型的变量,并且
- 左侧的
*
取消引用此指针,因此 FunctionB
的 return 值被分配给它指向的任何内存位置(方便地,恰好是 FunctionA
). 的位置
但是,当然,所有这一切都依赖于(非标准)假设,即在特定的编译器和平台上,此代码的目的是将 DWORD_PTR
写入内存,然后使用相同的内存位置作为函数指针实际工作并调用预期函数,而不是触发访问冲突、跳转到错误地址或 making demons fly out of your nose.
好的,这是丑陋的代码。那我该怎么做比较好呢?
好吧,理想情况下,我会更改 FunctionB
以便它实际上 return 一个适当类型的函数指针,这样就需要 none 这些转换恶作剧首先。
如果由于某种原因这真的不可能(我会非常努力地 使 成为可能,甚至在必要时重新设计 API,下一个最佳解决方案是显式转换 FunctionB
的 return 值。当然,这是未定义的行为,但至少它明确说明了它试图做什么。
无论哪种方式,我肯定会 typedef
将实际的函数指针类型转换为更具可读性的类型。这样,代码(带有显式转换)可能最终看起来像这样:
typedef BOOL (WINAPI * my_func_ptr_t) (arg1, arg2, etc...);
my_func_ptr_t FunctionA = NULL;
/* ... */
FunctionA = (my_func_ptr_t) FunctionB( var1, var2, etc... );
*(DWORD_PTR*)&FunctionA = FunctionB( var1, var2, etc...);
这段代码是什么意思?它有什么作用?
我尝试搜索 Google,但我不知道该使用什么术语。
之前的代码中有:
BOOL (WINAPI * FunctionA) (var1, var2, etc...) = NULL;
它标识了 "FunctionA" 是什么。
我假设是 *(DWORD_PTR*)&functionA
部分让您感到困惑?
让我们把它分解成几个部分。让我们从 &functionA
开始。它采用 functionA
的地址(无论是什么)和 return 指向它的指针。
然后我们有 (DWORD_PTR*)
将指向 functionA
的指针转换为指向 DWORD_PTR
的指针。
最后是开头唯一的 *
,它是解引用运算符,它接受一个指针并为您提供 if 指向的值。
和函数调用放在一起,就是简单的把调用functionB
的结果赋值给变量functionA
.
我只是在猜测,但有可能 functionB
return 是一个以某种通用方式指向函数的指针(因为 DWORD_PTR
是我的猜测)然后将其分配给变量 functionA
,该变量可能具有指向函数的类型指针。转换和寻址和取消引用运算符是因为 return 类型 functionB
。 我猜。没有更多信息或上下文,就无法确定。
这是丑陋的代码,就是这样。
它基本上所做的是调用一个函数 (FunctionB
),该函数 return 是指向另一个函数的指针,并将该指针分配给变量 FunctionA
。现在,如果仅此而已,那么代码将看起来非常简单:
FunctionA = FunctionB( var1, var2, etc... );
不幸的是,由于某些奇怪的原因(这可能对最初设计 API 的人来说很有意义),FunctionB
的 return 类型是 not 声明为函数指针,而是 DWORD_PTR
(与底层平台上的指针大小匹配的整数类型)。这意味着 FunctionB
的 return 值不能直接分配给变量 FunctionA
,而必须首先转换为实际的函数指针(正如注释中所指出的那样, 根据 C 标准在技术上是未定义的行为,尽管 POSIX 确实为它定义了语义)。
现在,如果 FunctionA
变量的类型很简单,比如 my_func_ptr_t
,那么这仍然很容易写:
FunctionA = (my_func_ptr_t) FunctionB( var1, var2, etc... );
但是,唉,在你的代码中 FunctionA
声明为:
BOOL (WINAPI * FunctionA) (arg1, arg2, etc...) = NULL;
这意味着它的类型类似于 BOOL (WINAPI *) (arg1, arg2, etc...)
,因此转换看起来像这样:
FunctionA = (BOOL (WINAPI *) (arg1, arg2, etc...)) FunctionB( var1, var2, etc... );
似乎编写该代码的人认为这样的转换太复杂了,而是想出了一个技巧:不是将 FunctionB
的 return 值转换为函数指针,像这样将 FunctionA
转换为 DWORD_PTR
不是更容易吗:
(DWORD_PTR) FunctionA = FunctionB( var1, var2, etc... ); /* this doesn't work :( */
当然,那不会编译;强制转换只是将变量的 value 转换为另一种类型,您不能为转换后的值赋值。 (在技术术语中,a cast is not an lvalue.)但是等等,您 可以 分配给取消引用的指针!所以如果我们...
- 获取指向
FunctionA
的指针(因此将是指向函数指针的指针), - 将其转换为指向
DWORD_PTR
的指针,并且 - 取消引用该指针,
然后我们得到一个有效的 DWORD_PTR
左值,我们可以分配给它,它恰好与变量 FunctionA
共享相同的内存地址。没关系,根据 C 标准,所有这一切都会以六种方式调用未定义的行为——我们知道我们的编译器会按照我们期望的方式处理它,对吗?
所以,这正是代码的作用:
&FunctionA
returns 指向变量的指针FunctionA
,(DWORD_PTR *)
转换此指针,使其现在声称指向DWORD_PTR
类型的变量,并且- 左侧的
*
取消引用此指针,因此FunctionB
的 return 值被分配给它指向的任何内存位置(方便地,恰好是FunctionA
). 的位置
但是,当然,所有这一切都依赖于(非标准)假设,即在特定的编译器和平台上,此代码的目的是将 DWORD_PTR
写入内存,然后使用相同的内存位置作为函数指针实际工作并调用预期函数,而不是触发访问冲突、跳转到错误地址或 making demons fly out of your nose.
好的,这是丑陋的代码。那我该怎么做比较好呢?
好吧,理想情况下,我会更改 FunctionB
以便它实际上 return 一个适当类型的函数指针,这样就需要 none 这些转换恶作剧首先。
如果由于某种原因这真的不可能(我会非常努力地 使 成为可能,甚至在必要时重新设计 API,下一个最佳解决方案是显式转换 FunctionB
的 return 值。当然,这是未定义的行为,但至少它明确说明了它试图做什么。
无论哪种方式,我肯定会 typedef
将实际的函数指针类型转换为更具可读性的类型。这样,代码(带有显式转换)可能最终看起来像这样:
typedef BOOL (WINAPI * my_func_ptr_t) (arg1, arg2, etc...);
my_func_ptr_t FunctionA = NULL;
/* ... */
FunctionA = (my_func_ptr_t) FunctionB( var1, var2, etc... );