我在this中找到了以下代码示例:
addr.sin_addr.s_addr = *(long *)(host->h_addr);
h_addr
是一个 char
指针,host
是一个指向 hostent
类型结构的指针。 addr
是sockaddr_in
类型的结构,sin_addr
是in_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
数组的所有四个字节复制到单个 long
值 addr.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/