繁体   English   中英

难以理解C ++中的inet_ntop()的第二个参数

[英]Difficulty understanding second parameter of inet_ntop() in C++

我正在尝试根据此处提供的教程在C ++中创建一个基本的Web服务器:

https://vichargrave.github.io/articles/2013-02/tcp-ip-network-programming-design-patterns-in-cpp

并且在理解以下行时遇到麻烦:

inet_ntop(PF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, sizeof(ip)-1);

具体来说,我在理解第二个参数时遇到了麻烦:

(struct in_addr*)&(address->sin_addr.s_addr)

是在做。 该参数是一种我以前从未见过的语法,基于我所知道的它在做以下两件事之一:

它是将struct in_addr指针与地址中的给定字段进行“与” in_addr

它正在将address->sin_addr.s_addr的地址转换为struct in_addr*的指针

哪一个?

编辑:所以看来这是演员。 这使我想到另一个问题。 该参数似乎将in_addr_t类型的变量in_addr_t转换为没有意义的结构。 这是对它的正确看法还是在做其他事情?

另外,我参考以下页面以获取有关此功能的文档:

http://pubs.opengroup.org/onlinepubs/7908799/xns/netinetin.h.html http://pubs.opengroup.org/onlinepubs/009695399/functions/inet_ntop.html

为了更好地理解,请从右向左阅读。

(struct in_addr*)&(address->sin_addr.s_addr)

所以,

address->sin_addr.s_addr --> uses the "address" ptr to access sin_addr.s_addr

然后

&(address->sin_addr.s_addr) takes the address of s_addr.

然后

(struct in_addr*) casts the address taken by & to in_addr.

以上是有意义的,因为在这种情况下以下2是等效的

(struct in_addr*)&(address->sin_addr.s_addr) 
(struct in_addr*)&(address->sin_addr)

结构的地址与C / C ++中其第一个成员的地址相同。

要回答你的第一个问题,它确实是铸造的地址 address->sin_addr.s_addr领域的struct in_addr*指针。 由于该问题被标记为c++ ,因此C ++样式转换将使这一点更加清晰:

inet_ntop(PF_INET, reinterpret_cast<struct in_addr*>(&(address->sin_addr.s_addr)), ip, sizeof(ip)-1);

要回答第二个问题,它不是将变量本身强制转换为指针。 它将变量的地址转换为其他指针类型。 在这种情况下, s_addr字段的地址s_addr转换为struct in_addr*指针。 类型的第一个字段的地址与类型本身的地址相同。 因此,将s_addr地址 s_addrstruct in_addr*是安全的。

但是,话说回来,演员表是多余的 ,应该删除。 inet_ntop()的第二个参数是const void* ,任何指针都可以按原样分配给void* 当第一个参数是(AF|PF)_INET ,第二个参数必须是指向struct in_addr的指针,因此您应该使用sin_addr字段本身(实际上是in_addr )的地址,而不是其s_addr字段(即in_addr内的字段):

inet_ntop(AF_INET, &(address->sin_addr), ip, sizeof(ip)-1);

如果您具有IPv6地址(第一个参数是(AF|PF)_INET6 ),则第二个参数必须是指向struct in6_addr的指针,该指针将是sockaddr_in6sin6_addr字段:

inet_ntop(AF_INET6, &(address->sin6_addr), ip, sizeof(ip)-1);

为了支持这两个家族(首先使用inet_ntop()主要原因), address应该是指向struct sockaddr_storage的指针(该指针足以容纳任何struct sockaddr_...类型,但在这种情况下为IPv4和IPv6地址),并且ip必须至少为46个字符(最好使用INET6_ADDRSTRLEN定义的字符)。 然后,您可以执行以下操作:

switch (address->ss_family) 
{
    case AF_INET:
        inet_ntop(AF_INET, &(reinterpret_cast<struct sockaddr_in*>(address)->sin_addr), ip, sizeof(ip)-1);
        break;
    case AF_INET6:
        inet_ntop(AF_INET6, &(reinterpret_cast<struct sockaddr_in6*>(address)->sin6_addr), ip, sizeof(ip)-1);
        break;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM