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

Roy*_*son 2 c casting

我在这个例子中找到了以下代码:

addr.sin_addr.s_addr = *(long *)(host->h_addr);
Run Code Online (Sandbox Code Playgroud)

h_addris是一个char指针,host是指向类型结构的指针hostent.addr是类型的结构sockaddr_insin_addr类型是一个结构in_addr.s_addr是一个uint32.

大部分信息可以在这里找到:http://man7.org/linux/man-pages/man7/ip.7.html

我很确定(long)将char转换为long,但我不知道这些额外的星号是做什么的,特别是因为s_addr它不是指针.

有人能解释一下这里发生了什么吗?

Mad*_*ist 8

(long *)(host->h_addr)意思是解释host->h_addr为指向a的指针long.这不是很便携,但据推测long,这个系统的长度是32位.

另外一个明星在*(...)解除引用现在的long任务.这有效地将原始char数组的所有四个字节复制到单个long值中addr.sin_addr.s_addr.比较(long)(*host->h_addr),只会复制第一个char元素.

这种技术非常难以移植.它假设该long类型的大小和字节序.你可能会从一个事实,即一个暗示s_addruint32,做:

addr.sin_addr.s_addr = *(uint32_t *)(host->h_addr);
Run Code Online (Sandbox Code Playgroud)

这并不是更好,因为字节序仍然受到破坏.此外,uint32_t保证至少保持32位.它可以是任何更大的位数,当您尝试使用副本读取未分配的内存时,会调用未定义的行为(想象将32位char数据复制为64位整数).

未来有两种选择:

如果您的char数组已经是正确的字节顺序(即,您不关心是否h_addr[0]表示本地的最高或最低字节uint32_t),请使用memcpy:

memcpy(&(addr.sin_addr.s_addr), host->h_addr, 4);
Run Code Online (Sandbox Code Playgroud)

这可能是您需要的方法.另一方面,如果您希望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]);
Run Code Online (Sandbox Code Playgroud)

在那里可能需要有一些演员阵容uint32_t.

  • 稍微修正一下:你说“uint32_t”保证保存至少 32 位”,但实际上保证保存 _exactly_ 32 位。(“uint_least32_t”和“uint_fast32_t”分别表示至少 32 位的最小和“最快”整数类型,但“uint32_t”是固定宽度的。) (2认同)