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

时间:2013-11-22 05:02:11

标签: c casting type-conversion inet

我理解gethostbyname()函数。 那时我发现了以下示例程序。

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

现在我在我的系统上运行它。 它工作正常。有两件事令我困惑:

  1. inet_ntoa 函数中,我们的类型为inet_ntoa(*(struct in_addr *)*addrs)。 但是如果我们像inet_ntoa((struct in_addr) addrs)那样做类型的情况。那么它不起作用。 我无法理解这背后的原因。还请解释我在这里做了什么样的铸造。
  2. 当我理解这个程序时。我在循环时也无法理解以下内容。

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

    请解释一下。

  3. 假设有一个 char**test 指向字符串“india”。我们什么时候做过像test++这样的事情。它根据字符串大小递增。在这种情况下,它将增加6(5 + 1(空字符))。为什么会这样?

2 个答案:

答案 0 :(得分:1)

  

予。在inet_ntoa函数中,我们有类型case,如inet_ntoa(*(struct in_addr *)* addrs)。但是如果我们做像inet_ntoa((struct in_addr)addrs这样的类型的情况。)然后它不起作用。我无法理解这背后的原因。还请解释一下,在这里做了什么样的铸造。

为此您需要知道in_addr类型的定义是什么。来自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.

这里的结构有一个联合,我们感兴趣的是chars。由于addrs类型为char**,因此我们会*addrs得到char*这是char数组的衰减类型。在类型广告中,我们手动将char*转换为struct in_addr*。但是inet_ntoa按值而不是引用获取in_addr个对象。因此,我们将另一个*添加到已投放的类型,以将其从in_addr*更改为in_addr。如果不执行**addrs,则会提供char而不是in_addr

  

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

要理解此循环,您会看到从addrs加载struct hostent::h_aliases的位置,MSDN再次将其作为

A NULL-terminated array of alternate names.

addrs指向带有终止NULL元素的字符序列(字符串)数组。对于例如char *addrs[] = { "Delhi", "London", "New York", NULL };我们知道addrs非空,但*addrs仅非三次非空,第四个元素在被检查为while(*addrs)时将为NULL。

  

III。假设有一个char **测试指向字符串“india”。什么时候我们做过像++ ++这样的事情。它根据字符串大小递增。在这种情况下,它将增加6(5 + 1(空字符))。为什么这样?

错误! char **test = "india";是非法的。但是,就像我上面解释的那样,它将指向一系列这样的字符串。当你执行addrs++时,实际发生的事情不会根据字符串长度递增,而只是按元素递增。当您执行*addrs时,它会指向“德里”,然后addrs++*addrs现在将指向“伦敦”,依此类推。

我建议您阅读C FAQ以获取有关数组到指针衰减,指针算术等的详细信息。

答案 1 :(得分:0)

1&GT; inet_ntoa()函数转换给定的Internet主机地址        以网络字节顺序,以IPv4点分十进制表示法的字符串。        该字符串在静态分配的缓冲区中返回,该缓冲区        quent调用将覆盖。

int_ntoa的原型:

 char *inet_ntoa(struct in_addr in);

您正在编写“inet_ntoa((struct in_addr) addrs)”这一行是错误的。 在你的代码中,addr是双指针。你是“in_addr对象”的类型转换地址,这是错误的。

*(struct in_addr *)*addrs* ( (struct in_addr *)*addrs )表示:

1&GT;将*addr(又是地址)的值转换为“struct in_addr *”,即“in_addr *”类型。

2&GT; * ( (struct in_addr *)*addrs )表示in_addr类型的对象/值。

2&GT;第二:

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

这里,hostinfo - &gt; h_addr_list返回指向数组的指针,即它的第一个元素的地址。

addrs++意味着转向arry的下一个元素。当数组完成时*addr将为null。

inet_ntoa(*(struct in_addr *)*addrs,这会将所有字节地址转换为字符串。