c++转换问题
C++ conversion question
我知道我可以像这样正确地使用 WinApi函数DsGetDcName
:
DOMAIN_CONTROLLER_INFO* dcInfo = nullptr;
unsigned long res = ::DsGetDcName(nullptr,
nullptr,
nullptr,
nullptr,
0, &dcInfo);
我知道这是不自然的,但我想理解为什么不能这样写:
void* dcInfo = nullptr;
unsigned long res = ::DsGetDcName(nullptr,
nullptr,
nullptr,
nullptr,
0, (DOMAIN_CONTROLLER_INFO**) dcInfo);
if (res)
{
wchar_t* name;
name = static_cast<DOMAIN_CONTROLLER_INFO*> (dcInfo)->DomainControllerName;
}
第二个版本使用void*
作为指针类型,这就是为什么我在运行它时得到访问冲突(在调用::DsGetDcName
时)。但我不明白这是为什么?当为dcInfo
指定void*
而不是类型DOMAIN_CONTROLLER_INFO* dcInfo
时,它是否与内存对齐的方式有关?
解决方案/strong>
我找到了问题,我可以使用复杂的不安全的void*版本,我只是没有传递正确的指针地址给那个函数。
void* dcInfo = nullptr;
unsigned long res = ::DsGetDcName(nullptr,
nullptr,
nullptr,
nullptr,
0, (DOMAIN_CONTROLLER_INFO**) &dcInfo);
注意我传递的是(DOMAIN_CONTROLLER_INFO**) &dcInfo
而不是(DOMAIN_CONTROLLER_INFO**) dcInfo
。我之前只是把自己关在脚上,因为我告诉编译器我知道我在做什么,但传递给函数一个指针值,而不是所需指针的地址(是的,指针值是nullptr
):-))
这是使用正确版本(版本1)的另一个原因。在第二种情况下,缺点也是必须像这样再次强制转换结果:
wchar_t* name;
name = static_cast<DOMAIN_CONTROLLER_INFO*>(dcInfo)->DomainControllerName; // Get DC
因为函数接受双间接指针。它类似于:
void AllocateMemory(int** pTarget)
{
*pTarget = new int[10];
(*pTarget)[0] = 110;
}
你可以这样称呼它:
int main()
{
int* pAllocHere;
AllocateMemory(&pAllocHere);
int nValue;
nValue= pAllocHere[0]; // 110
return 0;
}
将分配内存给您传递的int指针,并且必须传递指针的地址,而不仅仅是int**
类型转换的int*
。
这不是因为DsGetDcName
函数,而是由C/c++语言。函数不知道所需的大小,如果它为您分配它。有许多Windows函数需要两个函数调用—一个用于确定大小(主要是DWORD dwNeeded
),另一个用于实际执行该工作。此函数在一次调用中为您分配内存,并要求您稍后调用NetApiBufferFree。
在c++中,你可以使用int*&
来修改签名:
void AllocateMemory(int*& pTarget);
和调用:
int* pAllocHere;
AllocateMemory(pAllocHere);
但是Windows API必须使用C语言
您需要查看程序集。两个可用的选项(#2 )两者都使用LEA指令。这将把数据结构的地址加载到EAX中,在本例中为空。失败的示例加载该地址的值,该值为空。如你所知,你不能取消对null的引用。
// #1 - Fails
::DsGetDcName(nullptr, nullptr, nullptr, nullptr, 0, (DOMAIN_CONTROLLER_INFO**)void_ptr);
01101A63 mov esi,esp
01101A65 mov eax,dword ptr [void_ptr]
01101A68 push eax
01101A69 push 0
01101A6B push 0
01101A6D push 0
01101A6F push 0
01101A71 push 0
01101A73 call dword ptr [__imp__DsGetDcNameW@24 (1108350h)]
01101A79 cmp esi,esp
01101A7B call @ILT+310(__RTC_CheckEsp) (110113Bh)
// #2 - Works
::DsGetDcName(nullptr, nullptr, nullptr, nullptr, 0, (DOMAIN_CONTROLLER_INFO**)&void_ptr);
00EE1A63 mov esi,esp
00EE1A65 lea eax,[void_ptr]
00EE1A68 push eax
00EE1A69 push 0
00EE1A6B push 0
00EE1A6D push 0
00EE1A6F push 0
00EE1A71 push 0
00EE1A73 call dword ptr [__imp__DsGetDcNameW@24 (0EE8350h)]
00EE1A79 cmp esi,esp
00EE1A7B call @ILT+310(__RTC_CheckEsp) (0EE113Bh)
// #3 - Works
::DsGetDcName(nullptr, nullptr, nullptr, nullptr, 0, &dc_ptr);
013D1A5C mov esi,esp
013D1A5E lea eax,[dc_ptr]
013D1A61 push eax
013D1A62 push 0
013D1A64 push 0
013D1A66 push 0
013D1A68 push 0
013D1A6A push 0
013D1A6C call dword ptr [__imp__DsGetDcNameW@24 (13D8350h)]
013D1A72 cmp esi,esp
013D1A74 call @ILT+310(__RTC_CheckEsp) (13D113Bh)
- C++转换参数初始化问题
- 将父类对象强制转换为子类的问题
- 模板类转换问题 - 无法推断调用的函数
- 将旧管道转换为现代 openGL 时出现问题
- 将字节数组转换为带有字节序问题的指针
- 复制构造函数隐式转换问题
- 使用转换器提升 Python 问题 - 静态链接
- 与模板 (c++) 相关的转换问题
- 将文件复制到自定义位置,存在字符串转换问题
- 从基指针到派生的强制转换问题
- JNI 日期值转换问题,在C++中获取不同的长整型值
- 从 argv[1] 转换为字符 * 字符串后有什么问题?
- 将字符数组转换为结构时出现问题. 结构的字符数组变量溢出
- PX 转换例程编译问题
- 类型转换问题
- C++,遇到将双精度转换为整数的问题
- 拆分 pybind11 模块和自动类型转换问题
- 类型转换问题:返回为整数而不是浮点/类型
- Unicode 字符问题/转换参数
- c++和OpenCV:问题转换图像到灰度