了解 C 中的 getaddrinfo 函数
Understanding getaddrinfo function in C
我是 C 和套接字编程的新手,只是一个关于 getaddrinfo
函数的问题。 getaddrinfo
的函数原型为:
int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
和getaddrinfo
return是一个结果,指向一个addrinfo结构的链表,每个结构指向一个socket地址结构,对应host和service。
以下是我的问题:
Q1 - 为什么它需要 return 指向 链表 的 addrinfo
结构的结果?我的意思是给定一个主机和服务,这些只是一个唯一的套接字地址,它怎么可能不止一个有效的套接字地址,所以需要一个链表?
Q2-最后一个参数是struct addrinfo **result
,为什么是指向指针的指针?为什么它不是 struct addrinfo *result
,然后 getaddrinfo
在内部创建某物并让 result
(struct addrinfo *
) 指向它?
有人说这是由于 getaddrinfo
内部调用 malloc
,但我也可以这样编码
int main()
{
char *ptr_main;
test(ptr_main);
free(ptr_main);
}
void test(char * ptr)
{
ptr = malloc(10);
}
所以函数的参数是char *ptr
,而不是char **ptr
。
getaddrinfo()
returns 一个地址列表,因为一个主机名可以有多个地址。以那些需要通过不同 IP 分配访问者的高流量站点为例。
combines the functionality provided by the gethostbyname(3) and getservbyname(3) functions into a single interface, but unlike the latter functions, getaddrinfo() is reentrant and allows programs to eliminate IPv4-versus-IPv6 dependencies
它可能会触发 DNS 会话来解析主机名。对于上述那些高流量站点,相同的主机名将对应于实际地址列表。
你还问:
struct addrinfo **result
, why is it a pointer to a pointer?
在 C 中,指向某物的指针在必须修改某物时作为函数的参数传递。因此,例如,如果您需要修改一个整数,您可以传递 int *
。这种特殊的 修改 在 C 中很常见,当你想通过参数 return 某些东西时;在我们之前的示例中,我们可以通过访问作为参数传递的指针来 return 一个额外的整数。
但是如果一个函数想要分配一些东西怎么办?它将在内部产生 type * var = malloc()
,这意味着指向 type
的指针将被 returned。为了 return 它作为参数,我们需要传递一个 type **
参数。
逻辑清楚了吗?给定一个 type
,如果你想 return 它作为参数,你必须将它定义为指向 type
.
的指针
综上所述,在我们的例子中函数getaddrinfo
需要修改一个类型为struct addrinfo *
的变量,所以struct addrinfo **
是参数类型。
顺便提一下这个参数的含义:
The getaddrinfo() function allocates and initializes a linked list of addrinfo structures, one for each network address that matches node and service, subject to any restrictions imposed by hints, and returns a pointer to the start of the list in res. The items in the linked list are linked by the ai_next field.
如你所见,我们实际上在函数内部有一个分配。所以这个内存最终需要被释放:
The freeaddrinfo() function frees the memory that was allocated for the dynamically allocated linked list res.
为什么不只是一个 type *
参数?
您的代码示例导致未定义的行为,当我 运行 它导致程序崩溃。
为什么?是我上面写的,在C中参数是按值传递的。这意味着在 func(int c)
函数的情况下,以这种方式调用
int b = 1234;
funct(b);
函数内部使用的参数 c
将是 b
的 copy,对其的任何更改都不会在函数外保留.
在 func(char * ptr)
的情况下也会发生同样的情况(请注意巨大的间距,以强调类型是 char *
并且变量是 ptr
):[= 上的任何更改31=] 将无法在函数外存活。 **您将能够更改它指向的内存,并且这些更改将在函数 returns 之后可用,但作为参数传递的变量将与调用 [=33 之前相同=].
在您的示例中,在调用 test
之前,ptr_main
的值是多少?我们不知道,因为变量未初始化。因此,行为未定义。
如果你还有疑惑,这里有一个程序演示通过值获取的新分配的地址不能从外部访问the function
:
#include <stdlib.h>
#include <stdio.h>
void test(char * ptr)
{
ptr = malloc(10);
printf("test:\t%p\n", ptr);
}
int main()
{
char *ptr_main = (char *) 0x7777;
printf("main-1:\t%p\n", ptr_main);
test(ptr_main);
printf("main-2:\t%p\n", ptr_main);
}
输出:
main-1: 0000000000007777
test: 0000000000A96D60
main-2: 0000000000007777
即使在函数调用之后 ptr_main
的值与我初始化后的值相同 (0x7777
)。
我是 C 和套接字编程的新手,只是一个关于 getaddrinfo
函数的问题。 getaddrinfo
的函数原型为:
int getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
和getaddrinfo
return是一个结果,指向一个addrinfo结构的链表,每个结构指向一个socket地址结构,对应host和service。
以下是我的问题:
Q1 - 为什么它需要 return 指向 链表 的 addrinfo
结构的结果?我的意思是给定一个主机和服务,这些只是一个唯一的套接字地址,它怎么可能不止一个有效的套接字地址,所以需要一个链表?
Q2-最后一个参数是struct addrinfo **result
,为什么是指向指针的指针?为什么它不是 struct addrinfo *result
,然后 getaddrinfo
在内部创建某物并让 result
(struct addrinfo *
) 指向它?
有人说这是由于 getaddrinfo
内部调用 malloc
,但我也可以这样编码
int main()
{
char *ptr_main;
test(ptr_main);
free(ptr_main);
}
void test(char * ptr)
{
ptr = malloc(10);
}
所以函数的参数是char *ptr
,而不是char **ptr
。
getaddrinfo()
returns 一个地址列表,因为一个主机名可以有多个地址。以那些需要通过不同 IP 分配访问者的高流量站点为例。
combines the functionality provided by the gethostbyname(3) and getservbyname(3) functions into a single interface, but unlike the latter functions, getaddrinfo() is reentrant and allows programs to eliminate IPv4-versus-IPv6 dependencies
它可能会触发 DNS 会话来解析主机名。对于上述那些高流量站点,相同的主机名将对应于实际地址列表。
你还问:
struct addrinfo **result
, why is it a pointer to a pointer?
在 C 中,指向某物的指针在必须修改某物时作为函数的参数传递。因此,例如,如果您需要修改一个整数,您可以传递 int *
。这种特殊的 修改 在 C 中很常见,当你想通过参数 return 某些东西时;在我们之前的示例中,我们可以通过访问作为参数传递的指针来 return 一个额外的整数。
但是如果一个函数想要分配一些东西怎么办?它将在内部产生 type * var = malloc()
,这意味着指向 type
的指针将被 returned。为了 return 它作为参数,我们需要传递一个 type **
参数。
逻辑清楚了吗?给定一个 type
,如果你想 return 它作为参数,你必须将它定义为指向 type
.
综上所述,在我们的例子中函数getaddrinfo
需要修改一个类型为struct addrinfo *
的变量,所以struct addrinfo **
是参数类型。
顺便提一下这个参数的含义:
The getaddrinfo() function allocates and initializes a linked list of addrinfo structures, one for each network address that matches node and service, subject to any restrictions imposed by hints, and returns a pointer to the start of the list in res. The items in the linked list are linked by the ai_next field.
如你所见,我们实际上在函数内部有一个分配。所以这个内存最终需要被释放:
The freeaddrinfo() function frees the memory that was allocated for the dynamically allocated linked list res.
为什么不只是一个 type *
参数?
您的代码示例导致未定义的行为,当我 运行 它导致程序崩溃。
为什么?是我上面写的,在C中参数是按值传递的。这意味着在 func(int c)
函数的情况下,以这种方式调用
int b = 1234;
funct(b);
函数内部使用的参数 c
将是 b
的 copy,对其的任何更改都不会在函数外保留.
在 func(char * ptr)
的情况下也会发生同样的情况(请注意巨大的间距,以强调类型是 char *
并且变量是 ptr
):[= 上的任何更改31=] 将无法在函数外存活。 **您将能够更改它指向的内存,并且这些更改将在函数 returns 之后可用,但作为参数传递的变量将与调用 [=33 之前相同=].
在您的示例中,在调用 test
之前,ptr_main
的值是多少?我们不知道,因为变量未初始化。因此,行为未定义。
如果你还有疑惑,这里有一个程序演示通过值获取的新分配的地址不能从外部访问the function
:
#include <stdlib.h>
#include <stdio.h>
void test(char * ptr)
{
ptr = malloc(10);
printf("test:\t%p\n", ptr);
}
int main()
{
char *ptr_main = (char *) 0x7777;
printf("main-1:\t%p\n", ptr_main);
test(ptr_main);
printf("main-2:\t%p\n", ptr_main);
}
输出:
main-1: 0000000000007777
test: 0000000000A96D60
main-2: 0000000000007777
即使在函数调用之后 ptr_main
的值与我初始化后的值相同 (0x7777
)。