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 - 通过 argv 传递管道地址

c - 什么是 Windows DIB?

c++ - 仅当指针作为参数传递给函数时才存在类型别名问题吗?

c - 使用gdb时如何区分同名函数?

c - Linux/POSIX 等同于 Win32 的 CreateEvent、SetEvent、WaitForSingleObject

c - 错误: incompatible types when assigning to type ‘struct card’ from type struct card *’

c++ - `reinterpret_cast` a `T*` 到 `T(*)[N]` 是未定义的行为吗?

c - 这是否违反了严格的别名规则?

c++ - 如何在不违反严格的别名规则的情况下访问内存映射的多字节寄存器?

c++ - 通过引用访问是否违反了严格的别名规则?