简体   繁体   English

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

[英]Am I violating strict aliasing rules by creating dummy struct data types?

I have these two functions:我有这两个功能:

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);
}

Now, there's a type safety issue.现在,有一个类型安全问题。 For the first function, void pointer means Ethernet header.对于第一个函数,void 指针表示以太网头。 For the second function, void pointer means IPv4 header.对于第二个函数,void 指针表示 IPv4 标头。 This creates a huge possibility that somebody accidentally calls the second function for an Ethernet header directly.这创造了一个巨大的可能性,即有人不小心直接调用了以太网标头的第二个函数。 If somebody does so, the compiler gives no warning.如果有人这样做,编译器不会发出警告。

I would like to eliminate this type safety issue through two dummy structs the contents of which are never defined:我想通过两个从未定义其内容的虚拟结构来消除这种类型安全问题:

struct etherhdr;
struct ipv4hdr;

Now the functions would be:现在的功能是:

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);
}

This solves the type safety issue.这解决了类型安全问题。 Note I'm not actually accessing the Ethernet or IP headers through a struct which would be very bad practice indeed.注意我实际上并没有通过结构访问以太网或 IP 标头,这确实是非常糟糕的做法。

My question is, am I violating strict aliasing rules by defining such an API?我的问题是,我定义这样的 API 是否违反了严格的别名规则? Note the data is never accessed via the struct;请注意,数据永远不会通过结构访问; the data is just accessed via memcpy using a char pointer.数据只是使用 char 指针通过 memcpy 访问的。 My understanding is that char pointer can alias to anything.我的理解是 char 指针可以是任何东西的别名。

Let's leave the fact that Ethernet packet can contain IPv6 as irrelevant, as this was just a very simple example.让我们忽略以太网数据包可以包含 IPv6 的事实,因为这只是一个非常简单的例子。

As for answering your question, it was already answered by Cornstalks, no, you are not violating any strict aliasing rules.至于回答你的问题,Cornstalks 已经回答了,不,你没有违反任何严格的别名规则。
You may convert a pointer to a char pointer.您可以将指针转换为字符指针。 You may convert char pointer to another pointer if you are sure, that this another pointer is really there.如果您确定这个另一个指针确实存在,您可以将 char 指针转换为另一个指针。 See Strict aliasing rule and 'char *' pointers请参阅严格的别名规则和“char *”指针

The Standard allows implementations to impose alignment restrictions for structures which are coarser than those of any items contained therein.该标准允许实现对比其中包含的任何项目更粗糙的结构施加对齐限制。 This would allow an implementation for a platform that only supports aligned accesses, that was given eg这将允许仅支持对齐访问的平台的实现,例如

#include <string.h>
#include <stdint.h>
struct foo {uint32_t dat[1]; };
struct bar {uint16_t dat[2]; };
void test1(struct foo *dest, struct foo *src)
{
    memcpy(dest, src, 4);
}
void test2(struct bar *dest, struct bar *src)
{
    memcpy(dest, src, 4);
}

to generate code for test2 which is just as efficient as for test1 [using one 32-bit read and write, instead of two 16-bit reads and writes].test2生成与test1一样有效的代码[使用一个 32 位读写,而不是两个 16 位读写]。 If an implementation were to always pad all structures out to a multiple of four bytes and align them to four-byte boundaries, such an implementation would be allowed to perform the aforementioned optimization on test2 without having to know or care about how or even if struct bar is ever defined anywhere.如果一个实现总是将所有结构填充到四字节的倍数并将它们对齐到四字节边界,这样的实现将被允许在test2上执行上述优化,而无需知道或关心struct bar如何或什至struct bar可以在任何地方定义。

I don't know whether any present implementations would ever do such a thing, but I can hardly rule out the possibility that a future implementation might do so since there some circumstances where it could allow more efficient code generation.我不知道是否有任何当前的实现会做这样的事情,但我很难排除未来的实现可能会这样做的可能性,因为在某些情况下它可以允许更有效的代码生成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C 虚拟结构,严格别名和 static 初始化 - C dummy struct, strict aliasing and static initialization 兼容类型与严格别名规则 - compatible types vs. strict aliasing rules 在不违反严格的别名规则的情况下处理数据序列化 - Dealing with data serialization without violating the strict aliasing rule 不一致的严格别名规则 - Inconsistent strict aliasing rules 如何在不破坏严格别名规则的情况下有效地从char缓冲区复制小数据? - How can I copy small data efficiently from a char buffer without breaking the strict aliasing rules? 如何在不违反严格别名规则的情况下合法地使用类型惩罚与联合在struct sockaddr的变体之间进行投射? - How to legally use type-punning with unions to cast between variations of struct sockaddr without violating the strict aliasing rule? void** 是严格别名规则的例外吗? - Is void** an exception to strict aliasing rules? 分配对象的严格别名规则 - Strict aliasing rules for allocated objects 在类型之间按字节逐个复制数据是否会破坏严格的别名? - Does copying data byte wise between types break strict aliasing? 是否可以在不违反严格别名的情况下将字符数组用作 memory 池? - Is it possible to use a character array as a memory pool without violating strict aliasing?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM