为什么需要struct in_addr

Pen*_*uin 6 c sockets

我已经搜索过了。也许不好......我不明白为什么“in_addr”结构存在。

typedef uint32_t in_addr_t;

struct in_addr
{
    in_addr_t s_addr;
};
Run Code Online (Sandbox Code Playgroud)

问题是这个结构重要不重要。如果没关系的话我可以这样写:

*(uint32_t*)(&s->sin_addr) = to_be32(ip->addr);
Run Code Online (Sandbox Code Playgroud)

如果重要的话我应该这样写:

s->sin_addr.s_addr = to_be32(ip->addr);
Run Code Online (Sandbox Code Playgroud)

Jer*_*ner 7

由于结构中第一个成员变量的地址保证与结构本身的地址相同,并且由于该特定结构被修改的机会接近于零(因为这样做会破坏向后兼容性)世界上几乎所有已编译的网络可执行文件),在这种情况下,这并不重要。

然而,原则上,您可以想象这样一个场景:有人在 的顶部插入另一个成员变量struct in_addr,此时您的第一个示例(带有强制转换)将中断,而第二个示例将继续工作(重新编译后,课程)。

作为一般规则,尽可能避免显式强制转换是一个好主意,因为强制转换往往会覆盖编译器由于编程错误而报告的错误,从而导致可能的编译器错误变成影响运行时的故障用户和/或需要大量的侦探工作来诊断和修复。

至于为什么in_addr需要这个结构体——当他们设计 BSD 套接字 API 时,他们将其设计为能够同样良好地支持任意数量的多个网络协议,尽管每个网络协议都有自己的寻址方案需要跟踪不同的数据。最简单的方法(从软件设计的角度来看)是为每个协议提供自己的一组定义的结构,并设计 API 调用以获取指向任何结构类型的指针以及一个结构-size 值,以便相同的函数调用可以与任何支持的协议结合使用。in_addr为 IPv4 协议的网络地址概念定义的结构也是如此;事实上,它只有一个成员变量,这只是 IPv4 协议寻址方案(相对)简单性的结果,但这一事实不值得打破每个协议的结构抽象。


Cli*_*ord 7

是的,这很重要,因为它隐藏了实现细节。仅仅因为它在您的情况下包含一个in_addr_t,并不意味着在所有系统上都会如此。此外,正如您所假设的,in_addr_t甚至不需要与 兼容。uint32_t

Socket API 甚至不需要特定于 TCP/IP - 所有这些类型都经过抽象,以允许您的代码可以跨网络协议和操作系统移植。

因此,虽然它可能有效,但没有真正的优势,无论如何我认为它s->sin_addr.s_addr = to_be32(ip->addr);更简单、更容易理解,更重要的是不需要您了解底层实现。因此,*(uint32_t*)(&s->sin_addr) = to_be32(ip->addr);可能“有效”,但它不正确、不安全,甚至没有任何有用的目的。甚至是一个更长的表达!