我有这两个功能:
static inline void *ether_payload(void *pkt)
{
return ((char*)pkt) + 14;
}
static inline uint16_t ip_id(const void *pkt)
{
const char *cpkt = pkt;
uint16_t id;
memcpy(&id, &cpkt[4], sizeof(id));
return ntohs(id);
}
现在,有一个类型安全问题。对于第一个函数,void 指针表示以太网头。对于第二个函数,void 指针表示 IPv4 header 。这创造了一个巨大的可能性,即有人不小心直接调用了以太网 header 的第二个函数。如果有人这样做,编译器不会发出警告。
我想通过两个从未定义其内容的虚拟结构来消除这种类型安全问题:
struct etherhdr;
struct ipv4hdr;
现在的功能是:
static inline struct ipv4hdr *ether_payload(struct etherhdr *pkt)
{
return (struct ipv4hdr*)(((char*)pkt) + 14);
}
static inline uint16_t ip_id(const struct ipv4hdr *pkt)
{
const char *cpkt = (const char*)pkt;
uint16_t id;
memcpy(&id, &cpkt[4], sizeof(id));
return ntohs(id);
}
这解决了类型安全问题。注意我实际上并没有通过结构访问以太网或 IP header ,这确实是非常糟糕的做法。
我的问题是,我定义这样的 API 是否违反了严格的别名规则?请注意,数据永远不会通过结构访问;数据只是使用 char 指针通过 memcpy 访问的。我的理解是 char 指针可以是任何东西的别名。
让我们忽略以太网数据包可以包含 IPv6 的事实,因为这只是一个非常简单的例子。
最佳答案
至于回答你的问题,Cornstalks 已经回答了,不,你没有违反任何严格的别名规则。
您可以将指针转换为字符指针。如果您确定这个另一个指针确实存在,您可以将 char 指针转换为另一个指针。
见 Strict aliasing rule and 'char *' pointers
关于c - 我是否通过创建虚拟结构数据类型违反了严格的别名规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49722089/