c - 我是否通过创建虚拟结构数据类型违反了严格的别名规则?

标签 c strict-aliasing

我有这两个功能:

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/

相关文章:

c - 屏蔽掉c中不需要的位

c - 矩阵分离素数和复合然后对它们进行排序

c++ - C++ union 中的两个数组

c - 严格的别名规则是什么?

c++ - 违反严格别名,即使没有任何转换?

c - 如何从另一个 C 程序中调用一个 C 程序

c - 良好的C字符串库

c - 使用 fwrite() 在 C 中覆盖 ID3v2 标记

c - 如何在符合 C 标准的情况下通用地转换指针的地址

c - 是 unsigned char a[4][5]; [1][7];未定义的行为?