【发布时间】:2018-04-08 19:51:04
【问题描述】:
我有这两个功能:
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 标头。这产生了很大的可能性,即有人不小心直接调用了以太网标头的第二个函数。如果有人这样做,编译器不会给出警告。
我想通过两个从未定义其内容的虚拟结构来消除这种类型安全问题:
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 标头,这确实是非常糟糕的做法。
我的问题是,我定义这样的 API 是否违反了严格的别名规则?请注意,数据永远不会通过结构访问;只需使用 char 指针通过 memcpy 访问数据。我的理解是 char 指针可以是任何东西的别名。
让我们把以太网数据包可以包含 IPv6 的事实作为无关紧要的事实,因为这只是一个非常简单的示例。
【问题讨论】:
-
char*确实允许别名。我在这里没有看到任何严格的别名违规。
标签: c strict-aliasing