将含数组的结构体数组扁平化是否属于C++未定义行为?
问题解答
结论:即使结构体S不存在内存填充,这种将结构体数组扁平化处理的操作属于C++标准定义的未定义行为,具体原因如下:
指针运算的合法范围限制:C++标准明确规定,指针的算术运算和解引用只能在单个数组对象的范围内(或数组末尾的一个“哨兵”位置)进行。这里
s[0].v是第一个S实例中的数组,它的合法指针范围是s[0].v到s[0].v + 5。当你将指针p移动到s[0].v + 5之后,已经超出了第一个数组的合法范围,此时的指针运算(如p + 5及后续操作)本身就是未定义行为,更不用说对这些超出范围的指针进行解引用了。独立对象的内存边界:每个
S对象都是独立的内存实体,哪怕结构体数组在内存中连续排列且无填充,C++标准也不允许将多个S对象内的数组合并视为单个大数组访问。标准仅保证同一数组内的元素连续,以及结构体数组的元素在内存中连续排列,但不认可跨对象的数组元素构成一个逻辑上的连续数组。static_assert无法突破规则:static_assert(sizeof(S) == 5 * sizeof(int))只是确保了结构体没有内存填充,满足了内存布局的连续性,但这并未改变标准对指针操作的约束。内存布局连续不等于语言层面允许这种跨对象的数组访问方式。
实际编译运行时,GCC、MSVC等编译器可能会按照直观的内存布局处理这段代码,让它正常输出结果,但这属于编译器的非标准扩展行为,并非C++标准所保证的。依赖这种行为的代码,在其他编译器、不同优化等级或不同平台下可能出现不可预期的错误。
内容的提问来源于stack exchange,提问作者umbert
相关产品推荐
相关产品推荐

