POSIX 打算将指针指向可转换的变体struct sockaddr
,但是根据 C 标准的解释,这可能违反了严格的别名规则,因此违反了 UB。(请参阅此答案及其下方的评论。)我至少可以确认 gcc 至少可能存在问题:此代码Bug!
在启用优化和Yay!
禁用优化的情况下打印:
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
sa_family_t test(struct sockaddr *a, struct sockaddr_in *b)
{
a->sa_family = AF_UNSPEC;
b->sin_family = AF_INET;
return a->sa_family; // AF_INET please!
}
int main(void)
{
struct sockaddr addr;
sa_family_t x = test(&addr, (struct sockaddr_in*)&addr);
if(x == AF_INET)
printf("Yay!\n");
else if(x == AF_UNSPEC)
printf("Bug!\n");
return 0;
}
在在线 IDE上观察此行为。
要解决此问题,此答案建议使用带有联合的类型双关语:
/*! Multi-family socket end-point address. */
typedef union address
{
struct sockaddr sa;
struct sockaddr_in sa_in;
struct sockaddr_in6 sa_in6;
struct sockaddr_storage sa_stor;
}
address_t;
然而,显然事情并没有看起来那么简单……引用@zwol 的评论:
这可以工作,但需要相当小心。超出了我可以放入此评论框的内容。
它需要什么样的照顾?使用带有联合的类型双关语在 的变体之间进行转换的陷阱是什么struct sockaddr
?
我宁愿问也不愿遇到 UB。