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

C++标准中,结构体数组能否通过指针算术遍历对应数据成员?

结构体数组成员地址跳转的C++标准合法性问题

在类型为S的结构体数组中,相邻结构体的对应数据成员之间的字节偏移量确实等于sizeof(S)。那是否可以根据C++标准,通过将成员地址加上sizeof(S),直接从一个结构体的某个成员跳转到下一个结构体的对应成员?

示例代码如下:

#include <vector>
#include <string>
#include <iostream>

using namespace std;

struct S
{
    vector<int> v;
    string s;
    int i;
    char c;
};

void print_all(const string* s, size_t n, ptrdiff_t stride_in_bytes)
{
    while (n > 0)
    {
        cout << *s << "\n";
        --n;
        // 尝试从当前string成员跳转到下一个结构体的string成员
        s = reinterpret_cast<const string*>(reinterpret_cast<uintptr_t>(s)+stride_in_bytes);
    }
}

int main(int, char**)
{
    S my_array[3];
    my_array[0].s = "a";
    my_array[1].s = "b";
    my_array[2].s = "c";
    print_all(&my_array[0].s, 3, sizeof(S));
    return 0;
}

这段代码在GCC和MSVC中可以正常运行,但它是否符合C++标准?


结论:不符合C++标准,属于未定义行为

具体原因如下:

  • 指针运算规则限制:C++标准规定,指针的算术运算仅允许在同一个数组的元素范围内进行(或指向数组末尾的位置)。这里的string*指向的是各个独立S对象的成员,这些string本身并不构成一个数组。对这类指针进行偏移运算(哪怕通过uintptr_t转换后计算),已经违反了标准的指针操作规则。
  • 解引用的合法性未被保证:即便通过强制类型转换得到了一个新的string*,标准并不保证这个地址指向的是一个有效的、可访问的string对象。虽然实际编译器通常会按预期处理,但标准不对此行为负责,编译器有权进行任意优化,甚至生成错误代码。
  • 结构体布局的隐含风险:虽然结构体数组的元素通常是紧凑排列的,相邻成员的偏移看起来确实是sizeof(S),但标准允许编译器在特定场景下对结构体数组进行额外内存填充(尽管这种情况很少见),进一步增加了行为的不确定性。

实际编译器能运行这段代码,只是因为它们实现了超出标准要求的扩展行为,但这种代码不具备可移植性,也不能保证在所有编译器或优化级别下都正常工作。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:18:07