Question

I am understanding the gethostbyname() function. At that time I found the following sample program.

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

now I run it on my system. It is working fine. There are two things which are confusing me:

  1. 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.
  2. When I am understanding this program. I am also not able to understand the following while loop.

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

    Please explain me about it.

  3. 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?

No correct solution

OTHER TIPS

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.

For this you've to know what is the definition of the type in_addr is. From 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.

Here the structure has a union out of which our interest is in chars. Since addrs is of type char** when we do *addrs we get char* which is the decayed type of char array. In the type cast we manually convert char* to struct in_addr*. But inet_ntoa takes an in_addr object by value and not reference. Thus we add another * to the casted type to change it from in_addr* to in_addr. Without the case doing **addrs would give a char and not a in_addr.

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

To understand this loop you've see where you load addrs from: struct hostent::h_aliases which again MSDN documents as

A NULL-terminated array of alternate names.

addrs is pointing to an array of character sequences (strings) with a terminating NULL element. For e.g. char *addrs[] = { "Delhi", "London", "New York", NULL }; We know that addrs is non-null, but *addrs will be non-null only thrice, the fourth element would be NULL when checked as while(*addrs).

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?

Wrong! char **test = "india"; is illegal. However, like I've explained above, it'll be pointing to an array of such strings. When you do a addrs++, what really happens is not incremented based on the string length but just increment by an element. When you do *addrs it'll point to "Delhi", then addrs++ and *addrs will now point to "London" and so on.

I would recommend that you read C FAQ for details on array to pointer decay, pointer arithmetic, etc.

1> The inet_ntoa() function converts the Internet host address in, given in network byte order, to a string in IPv4 dotted-decimal notation. The string is returned in a statically allocated buffer, which subse‐ quent calls will overwrite.

Prototype of int_ntoa :

 char *inet_ntoa(struct in_addr in);

This line which you are writing "inet_ntoa((struct in_addr) addrs)" is wrong. As in your code addr is double pointer . you are type casting address to "in_addr object" which is wrong.

The line *(struct in_addr *)*addrs or * ( (struct in_addr *)*addrs ) means :

1.> convert value of *addr ( which is again a address ) to "struct in_addr *" i.e. "in_addr *" type.

2.> And * ( (struct in_addr *)*addrs ) means object/value of in_addr type.

2.> Second :

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

Here , hostinfo -> h_addr_list returns pointer to array i.e its address of first element.

addrs++ means moving to next elemnt in the arry. when array is finished *addr will be null.

inet_ntoa(*(struct in_addr *)*addrs , this will convert all byte address to string.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top