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

C++标准是否保证三种间接访问方式的行为均定义良好?

三种C++间接访问方式的标准合规性验证

问题背景

我实现了三种间接访问修改int变量的方式,测试了[[gnu::always_inline]] inline和[[gnu::noinline]]两种编译选项,输出均为10 12 14,想确认这三种方式是否均为C++标准定义的良好行为,可安全用于跨平台代码——尤其需要考虑**类型别名分析(Type-Based Alias Analysis, TBAA)**的影响。

测试代码如下:

#include <cstdint>
#include <iostream>
#include <any>

using namespace std;

#if 1
#define INLINE [[gnu::always_inline]] inline
#else
#define INLINE [[gnu::noinline]]
#endif

INLINE
void mod1(void *p) {
    *static_cast<int*>(p) = 10;
}

INLINE
void mod2(uintptr_t p) {
    *reinterpret_cast<int*>(p) = 12;
}

INLINE
void mod3(any p) {
    *any_cast<int*>(p) = 14;
}

int test1() {
    int a1 = 5;
    mod1(&a1);
    return a1;
}

int test2() {
    int a2 = 6;
    mod2(reinterpret_cast<uintptr_t>(&a2));
    return a2;
}

int test3() {
    int a3 = 6;
    mod3(&a3);
    return a3;
}

int main() {
    cout << test1() << "\n";
    cout << test2() << "\n";
    cout << test3() << "\n";
}

三种方式的标准合规性分析

1. mod1:void*转int*的访问

这种方式完全符合C++标准:

  • C++标准明确允许:将指向对象的指针转换为void*,再通过static_cast转换回原类型指针,得到的指针与原指针等价,可安全用于访问原对象。
  • 从TBAA角度看,最终解引用的是原类型int的指针,严格遵守类型别名规则(strict aliasing rule)——规则允许通过原类型指针访问对象,因此不会触发TBAA导致的未定义行为。

2. mod2:uintptr_t中转的指针访问

这种方式也是定义良好的:

  • 标准规定,uintptr_t(主流平台均支持,属于可选实现但几乎全平台提供)是一种无符号整数类型,能完整容纳void*的值。将int*转换为void*再转成uintptr_t,随后通过reinterpret_cast转回int*,得到的指针与原指针等价。
  • TBAA层面,最终同样是通过int*访问原int对象,符合strict aliasing规则,不存在未定义行为。

3. mod3:std::any中转的指针访问

这种方式同样符合标准:

  • std::any的设计目标就是存储任意类型的对象(包括指针),传入int*时,std::any会保存该指针的类型信息。
  • any_cast<int*>(p)在类型匹配时会返回正确的int*(类型不匹配时会抛出bad_any_cast异常,但此处传入的确实是int*,因此不会触发异常),解引用该指针修改原int对象完全合规。
  • TBAA角度,同样是通过原类型指针访问,无违规问题。

关于内联的补充

你测试的内联/非内联选项不影响结果,这是符合预期的:无论函数是否被内联,C++标准对指针转换、对象访问的规则都是强制性的,编译器必须保证这些操作的行为一致性。


内容的提问来源于stack exchange,提问作者Home of the Brave

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:35:19