Roman Mashak wrote:
Hello, All!
Short piece of code:
...
struct in_addr {
unsigned long int s_addr;
};
struct iphdr {
unsigned char ihl:4, version:4;
unsigned char tos;
short unsigned int tot_len;
short unsigned int id;
short unsigned int frag_off;
unsigned char ttl;
unsigned char protocol;
short unsigned int check;
unsigned int saddr;
unsigned int daddr;
};
extern char *inet_ntoa(struct in_addr);
struct iphdr *ip;
...
/* somewhere here 'ip' is filled in with values */
...
printf("%-15s ", inet_ntoa(ip->saddr));
Compiling with "gcc -Wall -g -ansi -pedantic" result with a warning: "
incompatible type for argument 1 of `inet_ntoa' ". I came to know the
solution is to change the call into:
printf("%-15s ", inet_ntoa(*(struct in_addr *)&ip->saddr));
But I can't entirely understand this construction - the conglomeration of
pointers and '&' operators, could you please explain it to me.
PS. It's not homework.
With best regards, Roman Mashak. E-mail: mr*@tusur.ru
The function is:
char *inet_ntoa(struct in_addr address);
Meaning: Function inet_ntoa, accepts an address parameter of type
"struct in_addr", and returns a pointer to data of type char.
Don't be fooled by the prototype. The "in_addr" is not a parameter name
but a type. Properly, it is "struct in_addr".
OK, so you are passing it:
inet_ntoa(*(struct in_addr *)&ip->saddr);
Meaning:
* = the data of
(struct in_addr *) = cast to a pointer to struct in_addr
& = the address of
ip->saddr = the integer saddr pointed to from ip
Now, re-arrange the above into English:
The data of, the address of the integer saddr in ip, cast to a pointer
of struct in_addr.
This is highly confusing. If I'm not mistaken, the code:
printf("%-15s ", inet_ntoa((struct in_addr)ip->saddr));
is what you really want but I'm guessing the compiler complained about
casting an int into a struct. Which is why you had to do the convoluted
thing you did.
An easier to understand code is:
extern char *inet_ntoa(struct in_addr);
struct iphdr *ip;
struct in_addr temp_addr;
...
/* somewhere here 'ip' is filled in with values */
...
temp_addr.s_addr = ip->saddr;
printf("%-15s ", inet_ntoa(temp_addr));
Just give the function what it wants and don't be too clever. The extra
temp variable is just 32 bits (typically), you're not saving that much
memory with your original method.