C++ 整数到指针的转换

3
最近我在处理WinAPI的WriteProcessMemoryReadProcessMemory,它们都将LPVOID作为第二个参数,这是我们要从另一个进程的内存中读取的实际地址。
考虑到这一点,这个整数转指针的转换是否正确的C++代码(没有未定义的行为等):
#include <windows.h>
int main()
{
    WriteProcessMemory(/*...*/,
        //want to read from memory address 0x1234 in the target process
        reinterpret_cast<void*>(static_cast<uintptr_t>(0x1234)),
        /*...*/);

    return 0;
}

据我所知,标准规定uintptr_t是一种整数类型,能够容纳指针而不改变指针的值。由于它是一个整数,我应该能够将0x1234存储在其中。标准还说,将uintptr_t重新解释为void*也会保持值不变。
1个回答

1
在Windows平台上,指针的存储方式与相同位数的整数类型完全相同。区别在于编译器如何解释指针和整数的值。因此,不需要进行转换。将其强制转换为void*/LPVOID仅是为了让编译器满意并接受整数值作为指针的位置,没有进行转换。在这种情况下,通过static_cast+reinterpret_cast过度处理了。
只要确定地址正确为0x1234,就不需要转换。只需使用简单的(LPVOID)0x1234或(void*)0x1234即可。
注:如评论中所述,常量可能会被截断。那么没有转换可以修复指针值。处理这种情况的一种方法是明确指定常量中使用的类型:
例如(void*) 0x1234567812345678ULL将是可以的,因为编译器被告知使用64位无符号类型。

这取决于您如何获取指针值。如果您有一个指针并执行 reinterpret_cast<uintptr_t>(static_cast<void *>(p)),然后打印该值-那么是的。 - bbonev
1
@MooingDuck 我明白你的意思,你是对的 - 0x1234像它现在这样是可以的(而且永远都是常量),但是0x1234567812345678ULL需要ULL(或者MS编译器用于64位常量的适当后缀)。顺便说一句,如果常量被截断了,任何复杂的转换也无法恢复它。 - bbonev
我对(void*)0x80000000发生的事情很好奇。我不确定它是否做了正确的事情。 - Mooing Duck
@bbonev:实际上,我认为0x1234567812345678会自动扩展,避免了这个问题。此外,(void *)0x80000000ULL也可以避免这个问题。 - Mooing Duck
好的,我想那回答了我的问题。谢谢你们两个。 - Tuntuni
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接