首先,我理解代码(见文章末尾)所做的一切,我不想要一个全面的解释。
我不明白的是这一行特殊的代码:memset(&提示,0,sizeof of (Struct));
到目前为止,我了解的是memset()是一个用来填充字符串的函数,它被指向上面。
它有三个参数,第一个是指向字符串的指针,第二个是要设置的值,第三个是设置为该值的字节数。
在这种情况下,要填充的值是&提示,这将是变量提示的入口。应该设置的值是0,因此它被填充为零。最后,它被填充到结构addrinfo的大小。
因此,在本例中,memset()为变量生成对结构大小的零提示。我做得对吗?
如果是,为什么在我的例子中需要这样做呢?
#include <stdlib.h>/* EXIT_SUCCESS */
#include <stdio.h>/* printf */
#include <string.h>/* memset() */
#include <errno.h>/* int errno */
#include <sys/types.h>/* socket defines */
#include <sys/socket.h>/* socket() */
#include <netdb.h>/* getaddrinfo() */
#define ECHO_PORT "7"
int main (int argc, char* argv[]){
if (argc != 2) {
printf ("Usage: %s HOSTNAME\n", argv[0]);
exit(EXIT_FAILURE);
}
/* Resolve host addresses: */
struct addrinfo hints;
struct addrinfo* result, *rp;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;/* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM;/* Stream socket */
hints.ai_flags = 0;
hints.ai_protocol = 0;/* Any protocol */
int err = getaddrinfo(argv[1], ECHO_PORT, &hints, &result);
/* Handle potential error: */
if (err) {
printf("Error: getaddrinfo: %s\n", gai_strerror(err));
exit(EXIT_FAILURE);
}
/* Print names found: */
printf("Addresses for %s:\n", argv[1]);
for (rp = result; rp != NULL; rp = rp->ai_next) {
int af = rp->ai_family;
char* address = NULL;
int ok;
if (AF_INET == rp->ai_family) {
uint8_t in_addr =((struct sockaddr_in*)rp->ai_addr)->sin_addr.s_addr;
address = malloc(INET_ADDRSTRLEN);
ok = inet_ntop(af, &in_addr, address, INET_ADDRSTRLEN);
}
if (AF_INET6 == rp->ai_family) {
char* in6_addr =((struct sockaddr_in6*)rp->ai_addr)->sin6_addr.s6_addr;
address = malloc(INET6_ADDRSTRLEN);
ok = inet_ntop(af, in6_addr, address, INET6_ADDRSTRLEN);
}
if (ok) {
printf("%s\n", address);
}
else {
perror("inet_ntop");
}
free(address);
}
freeaddrinfo(result);
return EXIT_SUCCESS;
}
发布于 2020-12-17 17:33:34
是的,你的理解基本上是正确的。在将整个hints
变量传递给getaddrinfo()
之前,代码只是简单地用0x00
字节填充它。这是将hints
初始化到默认状态所必需的,这一点很重要,因为addrinfo
包含控制getaddrinfo()
行为的标志和内存指针。因此,您不能只让hints
处于未初始化状态,它将包含随机垃圾,这将导致未定义的行为、混淆getaddrinfo()
和/或导致内存损坏、崩溃等。
使用memset()
是在一次快速操作中将hints
的所有字段初始化为零的一种快速方法,而不是单独初始化每个字段。这样,您就可以专注于将值赋值给您真正感兴趣的字段。
初始化hints
的一个更简单的方法是这样做:
struct addrinfo hints = {0};
这将值-将第一个字段(ai_flags
)初始化为0,并将其余字段初始化为其默认值,在本例中为零。
发布于 2020-12-17 17:31:48
是的,你的理解是正确的。
它在下面的代码中是必需的,因为
struct addrinfo hints;
hints
未初始化,程序员希望确保所有字段都为零。
一个更简单的解决方案是直接初始化它:
addrinfo hints{}; // C++11 and later
struct addrinfo hints = {0}; /* C and C++ */
跳过memset
。
另一个选项是使用指定初始化器 (C99和C++20)使用正确的值初始化它。在C中,您可以按顺序指定字段,但不能在C++中指定,因此这个顺序可以在以下两种情况下工作:
struct addrinfo hints = { /* "struct" not needed in C++ */
.ai_flags = 0,
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
/* .ai_protocol and the rest will be zeroed */
};
对于没有指定初始化器的旧标准:
struct addrinfo hints = {
0,
AF_UNSPEC,
SOCK_STREAM
};
发布于 2020-12-17 17:32:14
在这里使用memset
将hints
的所有字节设置为零是正确的。
这样做的目的是使以后没有显式设置的任何字段的值为0。由于hints
未初始化,其字段具有不定值,因此将所有字段设置为0。如果您查看struct addrinfo
的定义
struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
您可以看到,程序只显式地设置前4个字段。对memset
的调用首先处理其余部分。
https://stackoverflow.com/questions/65345553
复制相似问题