使用数组指针访问结构体成员是否符合C++标准?是否存在未定义行为?
问题说明
我定义了一个包含三个int成员的结构体:
struct ints{ int int1; int int2; int int3; };
尝试使用int (*)[3]类型的指针访问该结构体成员:
ints i = {1,2,3}; int (*p)[3] = (int (*)[3])&i; std::cout << (*p)[0] << std::endl; std::cout << (*p)[1] << std::endl; std::cout << (*p)[2] << std::endl;
目前运行正常,但不确定这是否属于C++标准中的未定义行为。另外,若结构体包含四个int成员,仍使用int (*)[3]指针访问会怎样?
问题解答
三个int成员的结构体情况
虽然你的代码在大多数主流编译器上都能正常输出预期结果,但从C++标准的角度来说,这属于未定义行为,原因如下:
- 违反了C++的严格别名规则:该规则规定,不能通过一个与对象实际类型不兼容的类型指针访问对象。
ints是结构体类型,int[3]是数组类型,二者属于不同类型,且不在严格别名规则的例外范围内(例外仅包括char*/unsigned char*/std::byte*等)。 - 即便当前编译器下两种类型内存布局完全一致(标准布局结构体成员按声明顺序排列,同类型成员间无填充),标准也不保证这种跨类型访问的合法性。编译器可能基于类型信息做优化,导致代码出现不可预期的行为(比如访问被优化掉、数值错乱等)。
四个int成员的结构体情况
如果结构体包含四个int成员,继续用int (*)[3]指针访问会有两种明确的问题:
- 访问前三个成员(
(*p)[0]、(*p)[1]、(*p)[2])时,仍违反严格别名规则,属于未定义行为。 - 若尝试访问
(*p)[3],则属于数组越界访问,这本身就是明确的未定义行为——哪怕该位置对应结构体的第四个int成员,标准也不允许通过数组指针越界访问超出数组范围的内存,编译器对此没有任何行为保证。
内容的提问来源于stack exchange,提问作者iz0
相关产品推荐
相关产品推荐

