在C中看似无用的类型转换

时间:2014-07-24 15:30:02

标签: c casting

我在套接字上找到了this C教程,我遇到了这段代码:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]) {

    char *hostname = "www.google.com";
    char ip[100];
    struct hostent *he;
    struct in_addr **addr_list;
    int i;

    if ((he = gethostbyname(hostname)) == NULL) {
        herror("gethostbyname");
        return 1;
    }

    addr_list = (struct in_addr **) he->h_addr_list;

    for (i = 0; addr_list[i] != NULL; i++) {
        strcpy(ip, inet_ntoa(*addr_list[i]));
    }

    printf("%s resolved to: %s\n", hostname, ip);
    return 0;
}

对我来说似乎无用的部分是:

    addr_list = (struct in_addr **) he->h_addr_list;

    for (i = 0; addr_list[i] != NULL; i++) {
        strcpy(ip, inet_ntoa(*addr_list[i]));
    }

如果是这样的话,对我来说会更有意义:

    for (i = 0; he->h_addr_list[i] != NULL; i++) {
        strcpy(ip, he->h_addr_list[i]);
    }

所以我尝试了这个,它编译得很好,但是当我运行它时输出:

www.google.com resolved to: J}�

但预期的输出是:www.google.com resolved to: 74.125.225.17

我不知道为什么必须将he->h_addr_list (char **)类型转换为(struct in_addr **),然后才将每个地址转换回(char **)。< / p>

为什么这是必要的,对我来说似乎很奇怪。另外,为什么我的版本的输出都很奇怪?

1 个答案:

答案 0 :(得分:1)

h_addr_list的类型是char**,因为它指向恰好包含互联网地址的任意缓冲区。

互联网地址采用原始数字形式 - 例如,普通的IPv4地址适合32位整数。 (x.x.x.x,其中每个x为0-255 == 8位)

要将数字表单转换为您可以使用的字符串表单,您需要将地址传递给inet_ntoa。它为您格式化地址。

不幸的是,h_addr_list的类型与该调用不兼容,强制进行强制转换。如果要再次执行h_addr_list的类型,可能会以不需要强制转换的方式设置。