带“继承”结构的指针算术返回异常值问题求助
C语言结构体多态实现的指针错误修复与适配方案
核心错误分析
你代码里的指针算术完全用错了:
&toread取的是指针变量自身的地址(二级指针struct Child**),而非它指向的结构体实例地址。对二级指针做偏移,计算出的地址和目标结构体成员的内存位置毫无关系,自然会读到随机值。- 即便想用指针偏移,也需要先把
toread转为char*(字节级指针)再做偏移,因为C语言中指针运算的单位是其指向类型的大小,直接用struct Child*偏移会按struct Child的大小跳步,而非字节数。
通用适配方案(支持多Parent类型)
要同时支持Parent1、Parent2这类不同的结构体,需要在基结构体Child中加入类型标识,通过类型判断来处理不同结构体的成员读取。
修正后的完整代码
#include <stdio.h> #include <sys/types.h> enum parent_type{ parent_type_1, parent_type_2 }; struct Child{ enum parent_type type; // 新增类型标识,用于区分不同父结构体 int size_bytes; }; struct Parent1{ struct Child base; u_int16_t val; }; struct Parent2{ struct Child base; u_int8_t val; }; void readParentData(struct Child* toread){ printf("Byte size: %d\n", toread->size_bytes); // 根据类型标识处理不同结构体 switch(toread->type){ case parent_type_1: { struct Parent1* p1 = (struct Parent1*)toread; printf("Value: %d\n", p1->val); break; } case parent_type_2: { struct Parent2* p2 = (struct Parent2*)toread; printf("Value: %d\n", p2->val); break; } default: printf("Unknown parent type\n"); } } int main(){ // 测试Parent1 struct Parent1 p1; p1.val = 1000; p1.base.type = parent_type_1; p1.base.size_bytes = sizeof(p1.val); // 用sizeof替代硬编码,更可靠 struct Child* child_p1 = (struct Child*)&p1; readParentData(child_p1); // 测试Parent2 struct Parent2 p2; p2.val = 255; p2.base.type = parent_type_2; p2.base.size_bytes = sizeof(p2.val); struct Child* child_p2 = (struct Child*)&p2; readParentData(child_p2); }
指针偏移的正确写法(仅作参考,不推荐通用场景)
如果只针对单一Parent1类型,想通过指针偏移读取val,正确的写法是:
// 转成char*后按字节偏移,跳过Child结构体的大小 u_int16_t val_read = *((u_int16_t*)((char*)toread + sizeof(struct Child)));
但这种方式无法适配不同的结构体类型,一旦新增Parent3就需要修改代码,远不如类型标识+switch的方式灵活安全。
内容的提问来源于stack exchange,提问作者myaumyau
相关产品推荐
相关产品推荐

