首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >内存集函数在解析主机地址的程序中的应用

内存集函数在解析主机地址的程序中的应用
EN

Stack Overflow用户
提问于 2020-12-17 17:27:12
回答 3查看 204关注 0票数 0

首先,我理解代码(见文章末尾)所做的一切,我不想要一个全面的解释。

我不明白的是这一行特殊的代码:memset(&提示,0,sizeof of (Struct));

到目前为止,我了解的是memset()是一个用来填充字符串的函数,它被指向上面。

它有三个参数,第一个是指向字符串的指针,第二个是要设置的值,第三个是设置为该值的字节数。

在这种情况下,要填充的值是&提示,这将是变量提示的入口。应该设置的值是0,因此它被填充为零。最后,它被填充到结构addrinfo的大小。

因此,在本例中,memset()为变量生成对结构大小的零提示。我做得对吗?

如果是,为什么在我的例子中需要这样做呢?

代码语言:javascript
运行
复制
#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;

}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-12-17 17:33:34

是的,你的理解基本上是正确的。在将整个hints变量传递给getaddrinfo()之前,代码只是简单地用0x00字节填充它。这是将hints初始化到默认状态所必需的,这一点很重要,因为addrinfo包含控制getaddrinfo()行为的标志和内存指针。因此,您不能只让hints处于未初始化状态,它将包含随机垃圾,这将导致未定义的行为、混淆getaddrinfo()和/或导致内存损坏、崩溃等。

使用memset()是在一次快速操作中将hints的所有字段初始化为零的一种快速方法,而不是单独初始化每个字段。这样,您就可以专注于将值赋值给您真正感兴趣的字段。

初始化hints的一个更简单的方法是这样做:

代码语言:javascript
运行
复制
struct addrinfo hints = {0};

这将值-将第一个字段(ai_flags)初始化为0,并将其余字段初始化为其默认值,在本例中为零。

票数 2
EN

Stack Overflow用户

发布于 2020-12-17 17:31:48

是的,你的理解是正确的。

它在下面的代码中是必需的,因为

代码语言:javascript
运行
复制
struct addrinfo hints;

hints未初始化,程序员希望确保所有字段都为零。

一个更简单的解决方案是直接初始化它:

代码语言:javascript
运行
复制
addrinfo hints{}; // C++11 and later

struct addrinfo hints = {0}; /* C and C++ */

跳过memset

另一个选项是使用指定初始化器 (C99和C++20)使用正确的值初始化它。在C中,您可以按顺序指定字段,但不能在C++中指定,因此这个顺序可以在以下两种情况下工作:

代码语言:javascript
运行
复制
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 */
};

对于没有指定初始化器的旧标准:

代码语言:javascript
运行
复制
struct addrinfo hints = {
    0,
    AF_UNSPEC,
    SOCK_STREAM
};
票数 3
EN

Stack Overflow用户

发布于 2020-12-17 17:32:14

在这里使用memsethints的所有字节设置为零是正确的。

这样做的目的是使以后没有显式设置的任何字段的值为0。由于hints未初始化,其字段具有不定值,因此将所有字段设置为0。如果您查看struct addrinfo的定义

代码语言:javascript
运行
复制
       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的调用首先处理其余部分。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65345553

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档