结构体同类型连续字段能否无需_Alignof用指针算术访问?
在C语言中通过指针算术访问结构体连续同类型字段是否存在未定义行为?
这种写法确实存在未定义行为——哪怕你在x86-64 Linux上用GCC、Clang编译,Valgrind和UBSan检测都没出问题,也不能保证所有符合C标准的编译器都能正常处理。
核心原因:指针算术的适用范围有限
C标准对指针算术有严格限制:只有当指针指向数组元素(或数组末尾的下一个位置)时,做加减操作才是合法的。结构体里的连续同类型字段,哪怕内存上看起来挨着,也不属于同一个数组对象,所以对field_2的指针做+1操作,本质是在访问一个不存在的“数组元素”,这直接违反了标准规定。
数组和结构体的本质区别
- 数组的元素是严格连续布局的,编译器会自动处理填充以满足对齐要求,指针算术在数组上完全合法。
- 结构体的字段之间,哪怕是同类型连续声明,标准也没要求它们必须连续排列——虽然大多数情况下为了效率不会加填充,但标准允许编译器在字段之间插入填充字节(比如为了满足结构体整体的对齐要求)。就算没填充,指针算术的操作本身已经违反了标准,属于未定义行为。
为什么你的测试没出问题?
在x86-64平台上,long int是8字节,int是4字节,field_2之后不需要额外填充就能让field_3满足对齐要求,所以内存上两者确实是连续的。编译器和检测工具在这种场景下不会报错,但这只是特定平台的巧合,换个编译器或架构(比如某些嵌入式平台),结果可能完全不同——比如插入填充后,field_2_ptr +1会指向无意义的填充字节,访问它可能导致崩溃或读取垃圾值。
正确的写法(避免未定义行为)
直接用结构体成员访问操作符,这是完全符合标准的写法:
struct MyStruct { long int field_1; int field_2; int field_3; }; int main(void) { struct MyStruct my_struct; int field_3_value = my_struct.field_3; }
内容的提问来源于stack exchange,提问作者schuelermine
相关产品推荐
相关产品推荐

