C-*(long *)(host-> h_addr)是什么?做? [英] C - What does *(long *)(host->h_addr); do?
问题描述
我在此示例中找到了以下代码:
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)
将字符转换为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);
这实际上并没有改善,因为字节序仍然受到破坏.另外,保证 有两种选择: 如果您的 这可能是您需要的方法.另一方面,如果您希望 沿途可能需要对 I found the following code in this example: Most of this information can be found here: http://man7.org/linux/man-pages/man7/ip.7.html I'm pretty sure Can someone explain what is happening here? The additional star in This technique is extremely unportable. It assumes both the size and endianness of the This is not really any better because the endianness is still undermined. Also, There are two options going forward: If your This is likely to be the approach you need. If, on the other hand you want There probably need to be some casts to 这篇关于C-*(long *)(host-> h_addr)是什么?做?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋! uint32_t
至少保留 32位.它可以是任意数量的位,当您尝试使用副本读取未分配的内存时(将32位的 char
数据复制为64位的整数),这将引发未定义的行为.> 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 [1]<< 16)[2]<< 8)+(host-> h_addr [3]);
uint32_t
进行强制转换.addr.sin_addr.s_addr = *(long *)(host->h_addr);
h_addr
is is a char
pointer and host
is a pointer to a struct of type hostent
. addr
is a struct of type sockaddr_in
and sin_addr
is a struct of type in_addr
. s_addr
is a uint32
.(long)
casts the char to a long, but I don't know what the extra asterisks do, especially because s_addr
is not a pointer. (long *)(host->h_addr)
means to interpret host->h_addr
as a pointer to a long
. This is not very portable, but presumably a long
is 32 bits long on the system this was written for.*(...)
dereferences what is now a long
for assignment. This effectively copies all four bytes of the original char
array into the single long
value addr.sin_addr.s_addr
. Compare to (long)(*host->h_addr)
, which would only copy the first char
element.long
type. You might be tempted to take a hint from the fact that s_addr
is a uint32
and do:addr.sin_addr.s_addr = *(uint32_t *)(host->h_addr);
uint32_t
is guaranteed to hold at least 32 bits. It can be any larger number of bits, which would invoke undefined behavior when you tried to read unallocated memory with the copy (imagine copying your 32 bits of char
data as a 64-bit integer).char
array is already in the correct byte order (i.e., you don't care if h_addr[0]
represents the highest or lowest byte of a local uint32_t
), use memcpy
:memcpy(&(addr.sin_addr.s_addr), host->h_addr, 4);
h_addr[0]
to always end up in the highest byte, you need to respect the endianness of your system: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
along the way there.