对 memset 感到困惑

Posted

技术标签:

【中文标题】对 memset 感到困惑【英文标题】:Confused about memset 【发布时间】:2012-03-22 10:18:17 【问题描述】:

我在学习socket编程,遇到了这段代码。

struct addrinfo hints, *res, *p;
int status;
char ipstr[INET6_ADDRSTRLEN];

if (argc != 2) 
    fprintf(stderr,"usage: showip hostname\n");
    return 1;


memset(&hints, 0, sizeof hints); 
hints.ai_family = AF_UNSPEC; // AF_INET or AF_INET6 to force version
hints.ai_socktype = SOCK_STREAM;

if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) 
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
    return 2;

除了一个,我都明白。为什么这段代码 memset'ed 结构提示而不是 *res 和 *p?

【问题讨论】:

更好的方式是初始化hints而不是调用memset 【参考方案1】:

res 指针将由getaddrinfo 函数填充,因此不需要初始化为零。另一方面,hints 需要初始化,因此将整个结构设置为零,然后设置唯一需要设置的两个字段。

由于您没有在代码中使用p - 我无法对此发表评论。

【讨论】:

【参考方案2】:

getaddrinfo 的描述表明

getaddrinfo() 函数分配和初始化一个 addrinfo 结构的链表,每个匹配节点和服务的网络地址都有一个,受提示施加的任何限制,并在 res 中返回指向列表开头的指针。

这意味着您不需要hints 中的任何其他信息,而不是绝对必要的(否则该函数可能会产生不希望的输出)。此外,函数的“真实”结果在res 中返回,这意味着res 的当前内容被覆盖,所以你并不关心函数调用之前那里的内容(只要你是如果函数失败,则不会解释它)。

由于结构的成员(如addrinfo)在声明该类型的变量时没有以任何方式初始化,hints 最初包含“垃圾”——无论在分配变量的内存中发生了什么.因此,代码调用memset 以简单/快速的方式将所有成员清零(而不是将成员变量逐个设置为零)。

【讨论】:

【参考方案3】:

它不应该因为你只对全 0 进行 memset 提示。 res 和 p 也只是指针,在 memset 调用时不定位到任何位置。

这是预期的行为。让我知道您的例外情况,我将能够更好地帮助您。

【讨论】:

【参考方案4】:

为什么这段代码 memset'ed 结构提示而不是 *res 和 *p?

因为,您只调用了一次 memset,并且只将 &hints 作为参数传递给该 memset。

memset(&hints, 0, sizeof hints);

如果你想 memset *res & *p,首先你需要为它们分配内存,因为它们只是指针,然后你需要通过将它们作为参数传递来分别为它们中的每一个调用 memset。

【讨论】:

所以我可以 memset *res,但这没有意义,因为 getaddrinfo 无论如何都会覆盖它? 您不能 memset *res,因为指针无效(包含“垃圾”,因为它尚未初始化 - 因此指向无效的“对象”)。您可以 memset 指针本身 (res),但如果您想这样做,也很容易将零分配给它 (res=0;)。你是对的,函数调用将在返回时为res 分配一个新值。 -- 澄清:res的类型是struct addrinfo *(指向addrinfo结构的指针),*res的类型是struct addrinfo(结构本身,不是指针)

以上是关于对 memset 感到困惑的主要内容,如果未能解决你的问题,请参考以下文章

C - memset vs free

memset 对每个字节进行初始化 (0,-1)

memset() 对 va_list 的含义是啥?

memset, fill 对bool,int 赋值的效率

关于memset()

memset使用技巧