我已经搜索过了。也许不好......我不明白为什么“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)
由于结构中第一个成员变量的地址保证与结构本身的地址相同,并且由于该特定结构被修改的机会接近于零(因为这样做会破坏向后兼容性)世界上几乎所有已编译的网络可执行文件),在这种情况下,这并不重要。
然而,原则上,您可以想象这样一个场景:有人在 的顶部插入另一个成员变量struct in_addr
,此时您的第一个示例(带有强制转换)将中断,而第二个示例将继续工作(重新编译后,课程)。
作为一般规则,尽可能避免显式强制转换是一个好主意,因为强制转换往往会覆盖编译器由于编程错误而报告的错误,从而导致可能的编译器错误变成影响运行时的故障用户和/或需要大量的侦探工作来诊断和修复。
至于为什么in_addr
需要这个结构体——当他们设计 BSD 套接字 API 时,他们将其设计为能够同样良好地支持任意数量的多个网络协议,尽管每个网络协议都有自己的寻址方案需要跟踪不同的数据。最简单的方法(从软件设计的角度来看)是为每个协议提供自己的一组定义的结构,并设计 API 调用以获取指向任何结构类型的指针以及一个结构-size 值,以便相同的函数调用可以与任何支持的协议结合使用。in_addr
为 IPv4 协议的网络地址概念定义的结构也是如此;事实上,它只有一个成员变量,这只是 IPv4 协议寻址方案(相对)简单性的结果,但这一事实不值得打破每个协议的结构抽象。
是的,这很重要,因为它隐藏了实现细节。仅仅因为它在您的情况下包含一个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);
可能“有效”,但它不正确、不安全,甚至没有任何有用的目的。甚至是一个更长的表达!
归档时间: |
|
查看次数: |
302 次 |
最近记录: |