C-*(long *)(host-> h_addr)是什么?做? [英] C - What does *(long *)(host->h_addr); do?

查看:95
本文介绍了C-*(long *)(host-> h_addr)是什么?做?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  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); 

这实际上并没有改善,因为字节序仍然受到破坏.另外,保证 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 进行强制转换.

I found the following code in this example:

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.

Most of this information can be found here: http://man7.org/linux/man-pages/man7/ip.7.html

I'm pretty sure (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.

Can someone explain what is happening here?

解决方案

(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.

The additional star in *(...) 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.

This technique is extremely unportable. It assumes both the size and endianness of the 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);

This is not really any better because the endianness is still undermined. Also,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).

There are two options going forward:

If your 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);

This is likely to be the approach you need. If, on the other hand you want 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]);

There probably need to be some casts to uint32_t along the way there.

这篇关于C-*(long *)(host-&gt; h_addr)是什么?做?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆