簡體   English   中英

無法理解inet_ntoa函數中完成的類型轉換

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

我了解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)的類型區分的話, inet_ntoa((struct in_addr) addrs)它將無法正常工作。 我無法理解其背后的原因。 還請向我解釋一下,這里進行了哪種類型的轉換。
  2. 當我了解此程序時。 我也無法理解以下while循環。

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

    請給我解釋一下。

  3. 假設有一個char**test指向字符串“ india”。 每當Ever進行類似test++ 根據字符串大小遞增。 在這種情況下,它將增加6(5 + 1(null char。))。 為什么這樣?

I.在inet_ntoa函數中,我們像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數組的衰減類型。 struct in_addr*類型轉換中,我們將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是非null的,但是*addrs只會是非null的三次,當以while(*addrs)進行檢查時,第四個元素將為NULL。

III。 假設有一個char ** test指向字符串“ india”。 每當Ever,我們都會做類似test ++的事情。 根據字符串大小遞增。 在這種情況下,它將增加6(5 + 1(null char。))。 為什么這樣?

錯誤! char **test = "india"; 是非法的。 但是,就像我上面解釋的那樣,它將指向這樣的字符串數組。 當您執行addrs++ ,實際發生的情況不是根據字符串的長度增加,而是僅增加一個元素。 當您執行*addrs它將指向“ Delhi”,然后addrs++*addrs現在將指向“倫敦”,依此類推。

我建議您閱讀C FAQ,以獲得有關數組的詳細信息,包括指針衰減,指針算術等。

1> inet_ntoa()函數將Internet主機地址(以網絡字節順序給出)轉換為IPv4點分十進制表示形式的字符串。 該字符串將在靜態分配的緩沖區中返回,隨后的調用將被覆蓋。

int_ntoa的原型:

 char *inet_ntoa(struct in_addr in);

您正在編寫“ inet_ntoa((struct in_addr) addrs) ”的這一行是錯誤的。 如在您的代碼中,addr是double指針。 您將類型轉換地址鍵入“ 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++意味着移至arry中的下一個元素。 當數組完成時*addr將為null。

inet_ntoa(*(struct in_addr *)*addrs ,這會將所有字節地址轉換為字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM