简体   繁体   English

无法理解inet_ntoa函数中完成的类型转换

[英]Unable to understand the type casting done in the inet_ntoa function

I am understanding the gethostbyname() function. 我了解gethostbyname()函数。 At that time I found the following sample program. 当时我找到了以下示例程序。

#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    char *host, **names, **addrs;
    struct hostent *hostinfo;

    if(argc == 1) 
    {
        char myname[256];
        gethostname(myname, 255);
    host = myname;
    }
    else
    host = argv[1];

    hostinfo = gethostbyname(host);
    if(!hostinfo) 
    {
        fprintf(stderr, "cannot get info for host: %s\n", host);
        exit(1);
    }

    printf("results for host %s:\n", host);
    printf("Name: %s\n", hostinfo -> h_name);
    printf("Aliases:");
    names = hostinfo -> h_aliases;
    while(*names) 
    {
        printf("%s", *names);
        names++;
    }
    printf("\n");

    if(hostinfo -> h_addrtype != AF_INET) 
    {
        fprintf(stderr, "not an IP host!\n");
        exit(1);
    }

    addrs = hostinfo -> h_addr_list;
    while(*addrs) 
    {
        printf(" %s", inet_ntoa(*(struct in_addr *)*addrs));
        addrs++;
    }
printf("\n");
exit(0);
}

now I run it on my system. 现在我在系统上运行它。 It is working fine. 一切正常。 There are two things which are confusing me: 有两件事使我感到困惑:

  1. In the inet_ntoa function, we have type case it like inet_ntoa(*(struct in_addr *)*addrs) . inet_ntoa函数中,我们像inet_ntoa(*(struct in_addr *)*addrs)一样键入大小写。 But If we do the type case like inet_ntoa((struct in_addr) addrs) .Then It is not working. 但是,如果我们进行类似inet_ntoa((struct in_addr) addrs)的类型区分的话, inet_ntoa((struct in_addr) addrs)它将无法正常工作。 I am not able to understand the reason behind this. 我无法理解其背后的原因。 Please also explain me that what kind of type casting is done here. 还请向我解释一下,这里进行了哪种类型的转换。
  2. When I am understanding this program. 当我了解此程序时。 I am also not able to understand the following while loop. 我也无法理解以下while循环。

    while(*addrs) { printf(" %s", inet_ntoa(*(struct in_addr *)*addrs)); while(* addrs){printf(“%s”,inet_ntoa(*(struct in_addr *)* addrs)); addrs++; addrs的++; } }

    Please explain me about it. 请给我解释一下。

  3. Suppose there is a one char**test which is pointing to string "india". 假设有一个char**test指向字符串“ india”。 When Ever we done something like test++ . 每当Ever进行类似test++ It is incremented according to the string size. 根据字符串大小递增。 In this case It will be incremented by 6(5 + 1(null char.)). 在这种情况下,它将增加6(5 + 1(null char。))。 Why so? 为什么这样?

I. In the inet_ntoa function, we have type case it like inet_ntoa(*(struct in_addr *)*addrs). I.在inet_ntoa函数中,我们像inet_ntoa(*(struct in_addr *)* addrs)一样键入大小写。 But If we do the type case like inet_ntoa((struct in_addr) addrs).Then It is not working. 但是,如果我们进行inet_ntoa((struct in_addr)addrs)这样的类型区分,那么它就无法正常工作。 I am not able to understand the reason behind this. 我无法理解其背后的原因。 Please also explain me that what kind of type casting is done here. 还请向我解释一下,这里进行了哪种类型的转换。

For this you've to know what is the definition of the type in_addr is. 为此,您必须知道in_addr类型的定义是什么。 From MSDN 从MSDN

typedef struct in_addr {
  union {
    struct {
      u_char s_b1,s_b2,s_b3,s_b4;
    } S_un_b;
    struct {
      u_short s_w1,s_w2;
    } S_un_w;
    u_long S_addr;
  } S_un;
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

Members:
S_un
    S_un_b: An IPv4 address formatted as four u_chars.
    S_un_w: An IPv4 address formatted as two u_shorts.
    S_addr: An IPv4 address formatted as a u_long.

Here the structure has a union out of which our interest is in chars . 这里的结构具有一个联合,我们对chars感兴趣。 Since addrs is of type char** when we do *addrs we get char* which is the decayed type of char array. 由于addrs的类型为char**当我们执行*addrs我们会得到char* ,这是char数组的衰减类型。 In the type cast we manually convert char* to struct in_addr* . struct in_addr*类型转换中,我们将char*手动转换为struct in_addr* But inet_ntoa takes an in_addr object by value and not reference. 但是inet_ntoa按值而不是引用接受in_addr对象。 Thus we add another * to the casted type to change it from in_addr* to in_addr . 因此,我们向强制类型添加了另一个*,以将其从in_addr*更改为in_addr Without the case doing **addrs would give a char and not a in_addr . 如果不做这种情况, **addrs会给出一个char而不是in_addr

II. II。 while(*addrs) { printf(" %s", inet_ntoa(*(struct in_addr *)*addrs)); while(* addrs){printf(“%s”,inet_ntoa(*(struct in_addr *)* addrs)); addrs++; addrs的++; } }

To understand this loop you've see where you load addrs from: struct hostent::h_aliases which again MSDN documents as 要理解这个循环你已经看到你加载addrs距离: struct hostent::h_aliases再次MSDN文档作为

A NULL-terminated array of alternate names.

addrs is pointing to an array of character sequences (strings) with a terminating NULL element. addrs指向带有终止NULL元素的字符序列(字符串)数组。 For eg char *addrs[] = { "Delhi", "London", "New York", NULL }; 例如, char *addrs[] = { "Delhi", "London", "New York", NULL }; We know that addrs is non-null, but *addrs will be non-null only thrice, the fourth element would be NULL when checked as while(*addrs) . 我们知道addrs是非null的,但是*addrs只会是非null的三次,当以while(*addrs)进行检查时,第四个元素将为NULL。

III. III。 Suppose there is a one char**test which is pointing to string "india". 假设有一个char ** test指向字符串“ india”。 When Ever we done something like test++. 每当Ever,我们都会做类似test ++的事情。 It is incremented according to the string size. 根据字符串大小递增。 In this case It will be incremented by 6(5 + 1(null char.)). 在这种情况下,它将增加6(5 + 1(null char。))。 Why so? 为什么这样?

Wrong! 错误! char **test = "india"; is illegal. 是非法的。 However, like I've explained above, it'll be pointing to an array of such strings. 但是,就像我上面解释的那样,它将指向这样的字符串数组。 When you do a addrs++ , what really happens is not incremented based on the string length but just increment by an element. 当您执行addrs++ ,实际发生的情况不是根据字符串的长度增加,而是仅增加一个元素。 When you do *addrs it'll point to "Delhi", then addrs++ and *addrs will now point to "London" and so on. 当您执行*addrs它将指向“ Delhi”,然后addrs++*addrs现在将指向“伦敦”,依此类推。

I would recommend that you read C FAQ for details on array to pointer decay, pointer arithmetic, etc. 我建议您阅读C FAQ,以获得有关数组的详细信息,包括指针衰减,指针算术等。

1> The inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. 1> inet_ntoa()函数将Internet主机地址(以网络字节顺序给出)转换为IPv4点分十进制表示形式的字符串。 The string is returned in a statically allocated buffer, which subse‐ quent calls will overwrite. 该字符串将在静态分配的缓冲区中返回,随后的调用将被覆盖。

Prototype of int_ntoa : int_ntoa的原型:

 char *inet_ntoa(struct in_addr in);

This line which you are writing " inet_ntoa((struct in_addr) addrs) " is wrong. 您正在编写“ inet_ntoa((struct in_addr) addrs) ”的这一行是错误的。 As in your code addr is double pointer . 如在您的代码中,addr是double指针。 you are type casting address to "in_addr object" which is wrong. 您将类型转换地址键入“ in_addr对象”,这是错误的。

The line *(struct in_addr *)*addrs or * ( (struct in_addr *)*addrs ) means : *(struct in_addr *)*addrs* ( (struct in_addr *)*addrs )意思是:

1.> convert value of *addr ( which is again a address ) to " struct in_addr * " ie " in_addr * " type. 1.>将*addr值(也是地址)转换为“ struct in_addr * ”,即“ in_addr * ”类型。

2.> And * ( (struct in_addr *)*addrs ) means object/value of in_addr type. 2.>并且* ( (struct in_addr *)*addrs )表示in_addr类型的对象/值。

2.> Second : 2.>第二:

 addrs = hostinfo -> h_addr_list;
    while(*addrs) 
    {
        printf(" %s", inet_ntoa(*(struct in_addr *)*addrs));
        addrs++;
    }

Here , hostinfo -> h_addr_list returns pointer to array ie its address of first element. 在这里,hostinfo-> h_addr_list返回指向数组的指针,即它的第一个元素的地址。

addrs++ means moving to next elemnt in the arry. addrs++意味着移至arry中的下一个元素。 when array is finished *addr will be null. 当数组完成时*addr将为null。

inet_ntoa(*(struct in_addr *)*addrs , this will convert all byte address to string. inet_ntoa(*(struct in_addr *)*addrs ,这会将所有字节地址转换为字符串。

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

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