【发布时间】:2021-03-28 10:18:48
【问题描述】:
首先,我了解代码(见文章末尾)的一般作用,我不想要一个全面的解释。
我不明白的是这行特定的代码: memset(&hints, 0, sizeof(struct addrinfo));
到目前为止,我得到的是 memset() 是一个函数来填充它指向的字符串。
它有三个参数,第一个是指向字符串的指针,第二个是要设置的值,第三个是要设置的值的字节数。
在这种情况下,要填充的值是 &hints,这将是变量提示的地址。应该设置的值是 0,所以它用零填充。最后填充到 struct 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;
}
【问题讨论】:
-
你知道未初始化的变量默认值是不确定的吗?此处 memset 的重点是确保对象没有,因此任何可能未设置的字段都具有零值 - 而不是读取未定义行为的垃圾。如果这 4 个分配覆盖了结构中的所有字段,那么从技术上讲,memset 是多余的 - 但这可能是一种很好的做法,因为它可能会在以后获得更多字段,然后如果结构没有先清零,然后有人会爆炸,那么事情可能会爆炸试图读取未初始化的成员。顺便说一句,C++ 有更好的方法来做到这一点
-
请不要同时标记 C 和 C++,除非问题涉及两种语言之间的交互或差异。对于 C 和 C++,问题的答案可能不同,这可能会令人困惑。要针对 C 和 C++ 提出相同的问题,请输入两个单独的问题。由于您的代码似乎是 C 代码,因此我将删除 C++ 标记。如果您使用的是 C++ 而不是 C,那么您可以更改标签。
-
@EricPostpischil 我同意 - 我不得不改变我的 C++ 答案:-)
-
@underscore_d 感谢您提供背景信息。我不知道。
-
@EricPostpischil 谢谢你的提示。我会在以后的帖子中考虑这一点