我在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转换为很长的字符,但是我不知道多余的星号会做什么,尤其是因为s_addr
不是指针。
有人可以解释这里发生了什么吗?
答案 0 :(得分:8)
(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位。它可以是任意数量的位,当您尝试使用副本读取未分配的内存时,将引发未定义的行为(可以将char
数据的32位复制为64位整数)。
有两种选择:
如果您的char
数组已经按照正确的字节顺序(即,您不在乎h_addr[0]
代表本地uint32_t
的最高字节还是最低字节),请使用{ {1}}:
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]);
进行强制转换。
答案 1 :(得分:0)
我读的方式是“ addr.sin_addr.s_addr等于强制转换为host-> h_addr的long
指针的对象”,或更简短地说,“ addr.sin_addr.s_addr等于{{1 }}由host-> h_addr指向”。 long
可能是指向host->h_addr
以外的对象的指针-在这里,该地址被视为指向long的指针,并且指向该指针的long分配给了long
。
HTH。