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

标签 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. 当我理解这个程序的时候。我也无法理解以下 while 循环。

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

    请解释一下。

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

最佳答案

I. In the inet_ntoa function, we have type case it like 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. I am not able to understand the reason behind this. Please also explain me that what kind of type casting is done here.

为此,您必须知道 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.

这里的结构有一个 union ,我们感兴趣的是 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. Suppose there is a one char**test which is pointing to string "india". When Ever we done something like test++. It is incremented according to the string size. In this case It will be incremented by 6(5 + 1(null char.)). Why so?

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

我建议您阅读 C FAQ有关数组到指针衰减、指针算法等的详细信息。

关于c - 无法理解在 inet_ntoa 函数中完成的类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20137363/

相关文章:

c - 解释将Float转换为整数时的输出?

c++ - 从 float 转换为自定义数字类型

c - C 程序的 GCC 编译选项

c - 取 C 中半字节的最后 2 位

sql-server - 将 XML 转换成货币

c# - 我应该将属性声明为接口(interface)还是基类(当它们同时实现时)?

c++ - PACKET_TX_RING 只发送第一个数据包,然后不再做任何事情

c - 输出末尾有问号

c++ - static_cast 被滥用了吗?

python - 如何使用 python-can 修复损坏的 .blf 文件(来自 Vector 软件)