C - 什么是 *(long *)(host->h_addr);做?

标签 c casting

我在this中找到了以下代码示例:

addr.sin_addr.s_addr = *(long *)(host->h_addr);

h_addr 是一个 char 指针,host 是一个指向 hostent 类型结构的指针。 addrsockaddr_in 类型的结构,sin_addrin_addr 类型的结构。 s_addr 是一个 uint32

大部分信息都可以在这里找到:http://man7.org/linux/man-pages/man7/ip.7.html

我很确定 (long) 将 char 转换为 long,但我不知道额外的星号有什么用,尤其是因为 s_addr 不是指针。

谁能解释一下这里发生了什么?

最佳答案

(long *)(host->h_addr) 表示将host->h_addr 解释为指向long 的指针。这不是很便携,但据推测,long 在为其编写的系统上是 32 位长。

*(...) 中的额外星号取消引用现在用于赋值的 long。这有效地将原始 char 数组的所有四个字节复制到单个 longaddr.sin_addr.s_addr 中。与 (long)(*host->h_addr) 相比,它只会复制第一个 char 元素。

这种技术非常不便携。它采用 long 类型的大小和字节顺序。您可能想从 s_addr 是一个 uint32 的事实中得到一些提示,然后执行以下操作:

addr.sin_addr.s_addr = *(uint32_t *)(host->h_addr);

这并没有好到哪里去,因为字节顺序仍然被破坏了。此外,uint32_t 保证至少 32 位。它可以是任何更大的位数,当您尝试使用副本读取未分配的内存时,这会调用未定义的行为(想象一下将您的 32 位 char 数据复制为 64 位整数)。

future 有两种选择:

如果您的 char 数组已经是正确的字节顺序(即,您不关心 h_addr[0] 代表本地的最高字节还是最低字节uint32_t), 使用memcpy:

memcpy(&(addr.sin_addr.s_addr), host->h_addr, 4);

这可能是您需要的方法。另一方面,如果您希望 h_addr[0] 始终以最高字节结束,则需要尊重系统的字节顺序:

addr.sin_addr.s_addr = (host->h_addr[0] << 24) + (host->h_addr[1] << 16) + (host->h_addr[2] << 8) + (host->h_addr[3]);

可能需要对 uint32_t 进行一些强制转换。

关于C - 什么是 *(long *)(host->h_addr);做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52266584/

相关文章:

c - 如何有效地手动计算 C 中的模数?

C++ 类型转换 int 到 union

java - 为什么我需要在转换为字节之前将 Float 转换为 float ?

postgresql - Postgres CAST macaddr

java - 类型转换比较器为子类工作

c - 我怎样才能为 ioctl 选择一个好的魔法/类型数字?

c++ - 从十六进制中获取 LSB 的值(C 代码)

c - 打印 ELF 文件的符号表

c# - 如何将 C# 对象拆箱为动态类型

c - 带文件输入跳过条件的算法-C语言