传递含联合体的IPv6头结构体作为函数参数时成员无法识别
Linux IPv6驱动中含联合体的结构体成员访问问题
问题描述
在Linux IPv6网络驱动开发中,传递包含联合体的结构体作为函数参数时,函数内部无法识别结构体成员,也无法初始化这些成员。传递无联合体的结构体和函数指针均正常,仅含联合体的结构体成员无法被识别,修正函数参数后问题仍存在。
原代码
#include <stdint.h> typedef struct In6_addr { union { uint8_t u6_addr8[16]; uint16_t u6_addr16[8]; uint32_t u6_addr32[4]; } in6_u; }; typedef struct Ip6_hdr { union { struct ip6_hdrctl { uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, 20 bits flow-ID */ uint16_t ip6_un1_plen; /* payload length */ uint8_t ip6_un1_nxt; /* next header */ uint8_t ip6_un1_hlim; /* hop limit */ } ip6_un1; uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */ } ip6_ctlun; struct In6_addr ip6_src; /* source address */ struct In6_addr ip6_dst; /* destination address */ void (*set6)(struct Ip6_hdr*, union ip6_ctlun*, struct ip6_hdrctl*, uint32_t , uint16_t, uint8_t, uint8_t, uint8_t, uint16_t,uint32_t, uint8_t, uint16_t, uint32_t); } __packed; //corrected Function void set6(Ip6_hdr* k, ip6_ctlun*, ip6_hdrctl*, uint32_t ip6_un1_flow, uint16_t ip6_un1_plen, uint8_t ip6_un1_nxt, uint8_t ip6_un1_hlim, uint8_t ip6_un2_vfc, uint8_t u6_addr8, uint16_t u6_addr16, uint32_t u6_addr32) { k->ip6_un1_flow = ip6_un1_flow; k->ip6_un1_plen = ip6_un1_plen; k->ip6_un1_nxt = ip6_un1_nxt; k->ip6_un1_nxt = ip6_un1_nxt; } void constructIphdr6(Ip6_hdr* k) { k->ip6_un1_flow = 0; k->ip6_un1_plen = 0; k->ip6_un1_nxt = 0; k->ip6_un1_nxt = 0; k->set6 = set6; } int main() { Ip6_hdr k; constructIphdr6(&k); }
错误信息
error: no member named 'ip6_un1_flow' in 'Ip6_hdr' k->ip6_un1_flow = ip6_un1_flow; error: no member named 'ip6_un1_flow' in 'Ip6_hdr' k->ip6_un1_flow = 0;
解决方案
问题根源
ip6_un1_flow并非Ip6_hdr的直接成员,它是嵌套在Ip6_hdr的ip6_ctlun联合体中的ip6_un1结构体成员,所有类似的成员访问都缺少了中间层级。此外还存在typedef不完整、函数参数类型未定义的问题。
修正步骤
- 补全成员访问路径:访问嵌套成员时必须逐层访问,比如
k->ip6_ctlun.ip6_un1.ip6_un1_flow。 - 完善typedef定义:给
In6_addr的结构体命名,同时给联合体ip6_ctlun和结构体ip6_hdrctl添加typedef,避免函数参数类型未定义。 - 修正函数参数:移除无用的参数,让函数逻辑更清晰。
修正后代码
#include <stdint.h> // 完善In6_addr的typedef定义 typedef struct In6_addr { union { uint8_t u6_addr8[16]; uint16_t u6_addr16[8]; uint32_t u6_addr32[4]; } in6_u; } In6_addr; // 提前typedef嵌套的结构体和联合体 typedef struct ip6_hdrctl { uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, 20 bits flow-ID */ uint16_t ip6_un1_plen; /* payload length */ uint8_t ip6_un1_nxt; /* next header */ uint8_t ip6_un1_hlim; /* hop limit */ } ip6_hdrctl; typedef union ip6_ctlun { ip6_hdrctl ip6_un1; uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */ } ip6_ctlun; typedef struct Ip6_hdr { ip6_ctlun ip6_ctlun; In6_addr ip6_src; /* source address */ In6_addr ip6_dst; /* destination address */ void (*set6)(struct Ip6_hdr*, uint32_t, uint16_t, uint8_t, uint8_t, uint8_t); } __packed Ip6_hdr; // 修正函数实现,补全成员访问路径,移除无用参数 void set6(Ip6_hdr* k, uint32_t ip6_un1_flow, uint16_t ip6_un1_plen, uint8_t ip6_un1_nxt, uint8_t ip6_un1_hlim, uint8_t ip6_un2_vfc) { k->ip6_ctlun.ip6_un1.ip6_un1_flow = ip6_un1_flow; k->ip6_ctlun.ip6_un1.ip6_un1_plen = ip6_un1_plen; k->ip6_ctlun.ip6_un1.ip6_un1_nxt = ip6_un1_nxt; k->ip6_ctlun.ip6_un1.ip6_un1_hlim = ip6_un1_hlim; k->ip6_ctlun.ip6_un2_vfc = ip6_un2_vfc; } void constructIphdr6(Ip6_hdr* k) { // 补全成员访问路径 k->ip6_ctlun.ip6_un1.ip6_un1_flow = 0; k->ip6_ctlun.ip6_un1.ip6_un1_plen = 0; k->ip6_ctlun.ip6_un1.ip6_un1_nxt = 0; k->ip6_ctlun.ip6_un1.ip6_un1_hlim = 0; k->set6 = set6; } int main() { Ip6_hdr k; constructIphdr6(&k); // 示例调用set6函数 k.set6(&k, 0x60000000, 0, 0, 64, 0x60); return 0; }
内容的提问来源于stack exchange,提问作者Steven Vanhaeren
相关产品推荐
相关产品推荐

