2

我正在理解这个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函数中,我们有类型 case it like inet_ntoa(*(struct in_addr *)*addrs)。但是如果我们像inet_ntoa((struct in_addr) addrs).The 那样做类型案例,那么它就行不通了。我无法理解这背后的原因。还请解释一下这里进行了什么样的类型转换。
  2. 当我了解这个程序时。我也无法理解下面的 while 循环。

    while(*addrs) { printf(" %s", inet_ntoa(*(struct in_addr *)*addrs)); 地址++;}

    请解释一下。

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

4

2 回答 2

1

I. 在 inet_ntoa 函数中,我们有类似 inet_ntoa(*(struct in_addr *)*addrs) 的类型 case。但是如果我们做像 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将给出 achar而不是 a in_addr

二、while(*addrs) { printf(" %s", inet_ntoa(*(struct in_addr *)*addrs)); 地址++;}

要了解这个循环,您已经看到了从哪里加载addrsstruct hostent::h_aliasesMSDN 文档又是

NULL结尾的备用名称数组。

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

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

错误的!char **test = "india";是非法的。然而,就像我上面解释的那样,它将指向一个这样的字符串数组。当您执行 aaddrs++时,真正发生的不是基于字符串长度递增,而是仅递增一个元素。当你这样做时*addrs,它将指向“德里”,然后addrs++现在*addrs将指向“伦敦”,依此类推。

我建议您阅读C 常见问题解答,了解有关数组到指针衰减、指针算术等的详细信息。

于 2013-11-22T06:05:02.480 回答
0

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

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.> 将*addr(又是地址)的值转换为“ struct in_addr *”即“ in_addr *”类型。

2.> 并且* ( (struct in_addr *)*addrs )表示 in_addr 类型的对象/值。

2.> 第二:

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

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

addrs++表示移动到数组中的下一个元素。当数组完成时*addr将为空。

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

于 2013-11-22T05:50:58.200 回答