如何将argv[1]转换为LPCVOID?C++地址转换问题求助
问题根源与解决方法
你现在的代码犯了一个典型的错误:你把命令行参数的字符串指针本身转换成了LPCVOID,而不是把字符串里的十六进制数值解析成目标内存地址。
当你写(LPCVOID)argv[1]时,你拿到的是argv[1]这个字符串变量在程序内存中的首地址(也就是存储"161551C"这个字符串的内存位置),而不是把"161551C"转换成对应的0x161551C内存地址,这就是为什么输出和你预期完全不符的原因。
正确的实现步骤
要解决这个问题,你需要分两步走:
- 把命令行传入的十六进制字符串解析成一个能存储指针数值的整数类型(推荐用
uintptr_t,这是C++标准中专门用于存储指针的无符号整数类型,跨平台兼容) - 将这个整数类型安全地转换为
LPCVOID
完整代码示例
#include <iostream> #include <cstdlib> #include <cstdint> // 用于uintptr_t #include <stdexcept> // 用于异常处理 using namespace std; int main(int argc, CHAR* argv[]) { if (argc < 3) { cout << "Arg1 (hex address) and Arg2 are required." << endl; exit(EXIT_FAILURE); } LPCVOID address = nullptr; try { // 把十六进制字符串解析为uintptr_t类型,基数指定为16 uintptr_t addr_value = stoull(argv[1], nullptr, 16); // 安全转换为LPCVOID address = reinterpret_cast<LPCVOID>(addr_value); } catch (const invalid_argument& e) { cout << "Error: Arg1 is not a valid hexadecimal number." << endl; exit(EXIT_FAILURE); } catch (const out_of_range& e) { cout << "Error: Arg1 is out of the range of valid memory addresses." << endl; exit(EXIT_FAILURE); } // 以十六进制格式输出验证地址 cout << "Parsed address: 0x" << hex << reinterpret_cast<uintptr_t>(address) << endl; // 在这里调用需要LPCVOID参数的Windows API // 比如 SomeWindowsAPI(address, ...); return 0; }
关键细节解释
uintptr_t的作用:这个类型保证能容纳任意指针的数值,是指针和整数转换的安全选择,比直接用unsigned long或者unsigned int更可靠(尤其是在64位系统上)。stoull函数:C++标准库函数,用于把字符串转换为无符号长整型,第三个参数16表示按十六进制解析。如果输入的不是合法十六进制字符串,会抛出invalid_argument异常;如果数值超出范围,会抛出out_of_range异常。reinterpret_cast:这是C中用于指针和整数之间转换的正确类型转换方式,比C风格的强制转换更清晰,也更符合C的类型安全要求。
测试验证
当你执行myprog.exe 161551C时,程序会把字符串"161551C"解析为0x161551C,输出的地址也会和你输入的十六进制值一致,这时再传入Windows API就能正常使用了。
内容的提问来源于stack exchange,提问作者learnerX
相关产品推荐
相关产品推荐

