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

时间:2018-09-10 23:02:14

标签: c casting

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

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

h_addrchar指针,而host是指向hostent类型的结构的指针。 addr是类型sockaddr_in的结构,而sin_addr是类型in_addr的结构。 s_addruint32

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

我很确定(long)将char转换为很长的字符,但是我不知道多余的星号会做什么,尤其是因为s_addr不是指针。

有人可以解释这里发生了什么吗?

2 个答案:

答案 0 :(得分:8)

(long *)(host->h_addr)意味着将host->h_addr解释为指向long的指针。这不是很可移植,但是在为它编写的系统上,long的长度可能为32位。

*(...)中的附加星号取消引用现在是long的分配对象。这样可以有效地将原始char数组的所有四个字节复制到单个longaddr.sin_addr.s_addr中。与(long)(*host->h_addr)相比,后者只会复制第一个char元素。

此技术极为难携带。它假定long类型的大小和字节序。您可能会想从s_addruint32的事实来暗示一下,然后这样做:

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。