C/C++函数内结构体数组指针偏移访问成员报错解决方法
错误原因
代码触发运行时错误来自两个核心问题:
- 运算符优先级逻辑错误:
->的优先级高于指针算术+和解引用*,原语句*(data + 1)->a = 3实际等价于*((data + 1)->a) = 3——先取偏移位置结构体的成员a(这是int类型的值,不是指针),再对这个随机未初始化的整数值做解引用,相当于把3写入随机内存地址,必然触发非法访问。 - 传参类型不匹配:
main中传入的&data是指向整个长度为3的结构体数组的指针(类型为x (*)[3]),但func的形参是x*(指向单个x结构体的指针),二者步长不一致,指针偏移计算出的内存地址完全错误。
修正方法
- 修正传参逻辑:数组传参直接传入数组名即可,数组名会隐式退化为指向首元素的指针,和形参类型完全匹配,即把
func(&data)改为func(data)。 - 函数内访问结构体数组成员有两种通用正确写法:
- 下标写法(可读性最高,日常开发推荐):通过下标定位元素后用
.访问结构体成员,编译器会自动计算正确的内存偏移data[1].a = 3; // 访问数组第2个元素(下标从0开始)的a成员 - 显式指针偏移写法:如果要手动实现指针算术,注意优先级控制,偏移后的指针本身就是指向目标结构体的指针,可以直接用
->访问成员,不需要额外解引用(data + 1)->a = 3; // 等价的解引用写法:(*(data + 1)).a = 3;
- 下标写法(可读性最高,日常开发推荐):通过下标定位元素后用
修正后可正常运行的完整代码
typedef struct { int a; int b; }x; int func(x *data){ // 访问数组第2个元素的a成员,两种写法选其一即可 data[1].a = 3; // (data + 1)->a = 3; return 0; } int main(){ x data[3]; // 正确传参,直接传入数组名 func(data); return 0; }
补充说明:指针算术的偏移单位和指针指向的类型大小绑定,当形参是
x*时,data + 1会自动向后偏移sizeof(x)个字节,刚好对应数组下一个元素的起始地址,不需要手动计算结构体大小做地址偏移。
内容的提问来源于stack exchange,提问作者user16234673
相关产品推荐
相关产品推荐

