memset这个函数的详细,要求有相应的示例代码和说明
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了memset这个函数的详细,要求有相应的示例代码和说明相关的知识,希望对你有一定的参考价值。
memset(str,0,80)是用0来初始化以地址str开始的80个连续单元..memset函数具体的用法是:
memset() 函数常用于内存空间初始化。如: char str[100]; memset(str,0,100); memset用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为‘ ’或‘\0’;例:char a[100];memset(a, '\0', sizeof(a)); memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。 strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘\0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。
参考资料:回答者:fyg0203jsj - 助理 二级 3-29 13:32
参考技术A void *memset( void *dest, int c, size_t count );dest是一个地址,c是0-255之间的值,count是要写的字节数。
这个函数的作用就是将dest到dest+count-1这段内存空间中每个字节都写成c。
下面这个例子是我从MSDN里拷的:
Example
/* MEMSET.C: This program uses memset to
* set the first four bytes of buffer to "*".
*/
#include <memory.h>
#include <stdio.h>
void main( void )
char buffer[] = "This is a test of the memset function";
printf( "Before: %s\n", buffer );
memset( buffer, '*', 4 );
printf( "After: %s\n", buffer );
Output
Before: This is a test of the memset function
After: **** is a test of the memset function
解析主机地址的程序中的 Memset 函数
【中文标题】解析主机地址的程序中的 Memset 函数【英文标题】:Memset function in programm that resolves host adresses 【发布时间】: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 谢谢你的提示。我会在以后的帖子中考虑这一点 【参考方案1】:是的,你理解正确。
在下面的代码中需要它,因为在
struct addrinfo hints;
hints
未初始化,程序员希望确保所有字段都归零。
一个更简单的解决方案是直接初始化它:
addrinfo hints; // C++11 and later
struct addrinfo hints = 0; /* C and C++ */
并跳过memset
。
另一个选择是使用designated initializers(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
;
【讨论】:
C 版本的初始化程序至少需要一个值。 0
是惯用的。我不确定 C++ 是否接受。
@JohnBollinger C++ 也接受了,所以我会补充一下,谢谢。
请注意,
仅适用于 C++11 及更高版本,但 0
将适用于所有 C++ 版本。
@RemyLebeau 哦,是的,最好也记下这一点,谢谢!【参考方案2】:
您说得对,这里使用了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
的调用首先会处理其余的事情。
【讨论】:
【参考方案3】:是的,你的理解基本正确。代码只是用0x00
字节填充整个hints
变量,然后将其传递给getaddrinfo()
。这是将hints
初始化为默认状态所必需的,这很重要,因为addrinfo
包含用于控制getaddrinfo()
行为的标志和内存指针。所以你不能只让hints
处于未初始化状态,它会包含随机垃圾,会导致未定义的行为、混淆getaddrinfo()
和/或什至导致内存损坏、崩溃等.
使用memset()
是一种在一次快速操作中将hints
的所有字段初始化为零的快速方法,而不是单独初始化每个字段。这样,您可以专注于为您真正感兴趣的字段分配值。
初始化hints
的更简单方法是:
struct addrinfo hints = 0;
这将 value-initialize 第一个字段 (ai_flags
) 为 0,而 default-initialize 其余字段为其默认值,在本例中为也是零。
【讨论】:
当然,“旧编译器”不仅包括那些实现旧版本 C++ 的编译器,还包括所有不提供初始化器语法扩展的 C 编译器。 问题现在被标记为 C。=
不是 any 语言的首选初始化方式。以上是关于memset这个函数的详细,要求有相应的示例代码和说明的主要内容,如果未能解决你的问题,请参考以下文章
c++这个memset()函数有啥用? memset(啥意思,啥意思,啥意思);