[英]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.