You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以符合C++标准的方式将进程内部内存地址赋值给指针?

符合C++标准的进程内存地址转指针方法

首先明确:你提到的两种直接将硬编码数值转换为指针的写法,确实属于未定义行为。C++标准仅规定了两种整数转指针的合法场景:

  • 该整数是从一个有效指针通过reinterpret_cast转换而来的整数值;
  • 该整数是空指针常量(比如0或nullptr对应的数值)。
    直接将手动指定的内存地址数值(如0x1000FFFF)转换为指针,标准未定义其行为,具体结果完全依赖编译器和平台。

关于汇编函数返回地址的合规性

通过汇编函数返回指定地址的方式,并不符合C标准。因为C标准并未对汇编代码的交互作出规定,这属于实现定义特性——是否可行、行为如何,完全由编译器和目标平台决定,不属于跨平台的标准合规写法。

更优的合规替代方案

C++标准本身不支持直接硬编码任意内存地址并转换为指针,但针对不同场景,有以下合规或更简洁的实现扩展方案:

1. 引用已知对象的地址

如果目标地址对应程序中已存在的全局/静态对象,直接获取其地址是完全合规的:

// 假设存在全局对象
CInterpretator global_interpretator;
CInterpretator* pInterpretatorObj = &global_interpretator;

2. 使用合法分配的内存地址

如果目标地址是通过标准库或平台API合法分配的内存区域(比如动态分配、内存映射),将分配得到的void*转换为目标指针类型是合规的:

// 示例:使用Windows平台API分配内存
void* mem = VirtualAlloc((LPVOID)0x1000FFFF, sizeof(CInterpretator), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (mem != nullptr) {
    CInterpretator* pInterpretatorObj = static_cast<CInterpretator*>(mem);
    // 注意:需手动构造对象(使用placement new)
    new (pInterpretatorObj) CInterpretator();
}

这里的转换是定义行为,因为mem指向的是合法分配的内存区域。

3. 利用编译器扩展声明固定地址变量

对于必须硬编码地址的场景(比如嵌入式硬件寄存器、第三方模块固定地址对象),可以使用编译器提供的扩展特性,比手写汇编更简洁:

  • GCC/Clang:使用__attribute__((address))声明变量在指定地址:
    CInterpretator* pInterpretatorObj __attribute__((address(0x1000FFFF)));
    
  • MSVC:使用__declspec(allocate)配合段声明,或__at属性(针对嵌入式场景):
    __declspec(allocate(".mysection")) CInterpretator* pInterpretatorObj = reinterpret_cast<CInterpretator*>(0x1000FFFF);
    // 需同时在链接脚本/项目设置中指定.mysection的地址为0x1000FFFF
    

这些是实现定义的特性,但比汇编写法更简洁,且被主流编译器广泛支持。


内容的提问来源于stack exchange,提问作者Alcatraz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 12:15:41