我理解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);
}
现在我在我的系统上运行它。 它工作正常。有两件事令我困惑:
inet_ntoa(*(struct in_addr *)*addrs)
。
但是如果我们像inet_ntoa((struct in_addr) addrs)
那样做类型的情况。那么它不起作用。
我无法理解这背后的原因。还请解释我在这里做了什么样的铸造。当我理解这个程序时。我在循环时也无法理解以下内容。
而(* addrs的) { printf(“%s”,inet_ntoa(*(struct in_addr *)* addrs)); addrs的++; }
请解释一下。
假设有一个 char**test
指向字符串“india”。我们什么时候做过像test++
这样的事情。它根据字符串大小递增。在这种情况下,它将增加6(5 + 1(空字符))。为什么会这样?
答案 0 :(得分:1)
予。在inet_ntoa函数中,我们有类型case,如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
数组的衰减类型。在类型广告中,我们手动将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。假设有一个char **测试指向字符串“india”。什么时候我们做过像++ ++这样的事情。它根据字符串大小递增。在这种情况下,它将增加6(5 + 1(空字符))。为什么这样?
错误! char **test = "india";
是非法的。但是,就像我上面解释的那样,它将指向一系列这样的字符串。当你执行addrs++
时,实际发生的事情不会根据字符串长度递增,而只是按元素递增。当您执行*addrs
时,它会指向“德里”,然后addrs++
和*addrs
现在将指向“伦敦”,依此类推。
我建议您阅读C FAQ以获取有关数组到指针衰减,指针算术等的详细信息。
答案 1 :(得分:0)
1&GT; inet_ntoa()函数转换给定的Internet主机地址 以网络字节顺序,以IPv4点分十进制表示法的字符串。 该字符串在静态分配的缓冲区中返回,该缓冲区 quent调用将覆盖。
int_ntoa的原型:
char *inet_ntoa(struct in_addr in);
您正在编写“inet_ntoa((struct in_addr) addrs)
”这一行是错误的。
在你的代码中,addr是双指针。你是“in_addr对象”的类型转换地址,这是错误的。
行*(struct in_addr *)*addrs
或* ( (struct in_addr *)*addrs )
表示:
1&GT;将*addr
(又是地址)的值转换为“struct in_addr *
”,即“in_addr *
”类型。
2&GT; * ( (struct in_addr *)*addrs )
表示in_addr类型的对象/值。
2&GT;第二:
addrs = hostinfo -> h_addr_list;
while(*addrs)
{
printf(" %s", inet_ntoa(*(struct in_addr *)*addrs));
addrs++;
}
这里,hostinfo - &gt; h_addr_list返回指向数组的指针,即它的第一个元素的地址。
addrs++
意味着转向arry的下一个元素。当数组完成时*addr
将为null。
inet_ntoa(*(struct in_addr *)*addrs
,这会将所有字节地址转换为字符串。