详解C语言中的memset()函数

C语言memset()函数:将内存的前n个字节设置为特定的值
头文件:

#include <string.h>

memset() 函数用来将指定内存的前n个字节设置为特定的值,其原型为:

  void * memset( void * ptr, int value, size_t num );

参数说明:
ptr 为要操作的内存的指针。
value 为要设置的值。你既可以向 value 传递 int 类型的值,也可以传递 char 类型的值,int 和 char 可以根据 ASCII 码相互转换。
num 为 ptr 的前 num 个字节,size_t 就是unsigned int。

【函数说明】memset() 会将 ptr 所指的内存区域的前 num 个字节的值都设置为 value,然后返回指向 ptr 的指针。

memset() 可以将一段内存空间全部设置为特定的值,所以经常用来初始化字符数组。例如:

char str[20];
memset(str, '\0', sizeof(str)-1);

【返回值】返回指向 ptr 的指针。

注意:参数 value 虽声明为 int,但必须是 unsigned char,所以范围在0 到255 之间。

范例:
复制纯文本新窗口

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
  // 不可以声明为 char *str = "http://c.biancheng.net";
  char str[] = "http://c.biancheng.net";
  memset(str, '-', 7);
  puts(str);
  system("pause");
  return EXIT_SUCCESS;
}

执行结果:

-------c.biancheng.net

memmove 和 memcpy的区别
memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下:

void *memcpy(void *dst, const void *src, size_t count);

void *memmove(void *dst, const void *src, size_t count);

他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。

第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。
第二种情况下,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。
实际上,memcpy只是memmove的一个子集。

二者的c语言实现很简单,有兴趣的朋友可以去看看。在实际情况下,这两个函数都是用汇编实现的。

memmove在copy两个有重叠区域的内存时可以保证copy的正确,而memcopy就不行了,但memcopy比memmove的速度要快一些,如:
char s[] = "1234567890";
char* p1 = s;
char* p2 = s+2;
memcpy(p2, p1, 5)与memmove(p2, p1, 5)的结果就可能是不同的,memmove()可以将p1的头5个字符"12345"正确拷贝至p2,而memcpy()的结果就不一定正确了

memcpy()、 memmove()和memccpy()

这三个函数的功能均是将某个内存块复制到另一个内存块。前两个函数的区别在于它们处理内存区域重叠(overlapping)的方式不同。第三个函数的功能也是复制内存,但是如果遇到某个特定值时立即停止复制。
    对于库函数来说,由于没有办法知道传递给他的内存区域的情况,所以应该使用memmove()函数。通过这个函数,可以保证不会出现任何内存块重叠问题。而对于应用程序来说,因为代码“知道”两个内存块不会重叠,所以可以安全地使用memcpy()函数。

关于memmove的实现:

void *mymemmove(void *dest, const void *src, size_t n)
{
  char temp[n];
  int i;
  char *d = dest;
  const char *s = src;

  for (i = 0; i < n; i++)
    temp[i] = s[i];
  for (i = 0; i < n; i++)
    d[i] = temp[i];

  return dest;
}

关于memcpy的实现:

void *mymemcpy(void *dest, const void *src, size_t n)
{
  char *d = dest;
  const char *s = src;
  int *di;
  const int *si;
  int r = n % 4;

  while (r--)
    *d++ = *s++;
  di = (int *)d;
  si = (const int*)s;
  n /= 4;
  while (n--)
    *di++ = *si++;

  return dest;
}
(0)

相关推荐

  • C++中memset函数用法详解

    本文实例讲述了C++中memset函数用法.分享给大家供大家参考,具体如下: 功 能: 将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作 用 法: void memset(void *s, char ch, unsigned n); 程序示例: #include <string.h> #include <stdio.h> #include <memory.h> int main(v

  • 深入学习C语言中memset()函数的用法

    头文件: #include <string.h> memset() 函数用来将指定内存的前n个字节设置为特定的值,其原型为: void * memset( void * ptr, int value, size_t num ); 参数说明: ptr 为要操作的内存的指针. value 为要设置的值.你既可以向 value 传递 int 类型的值,也可以传递 char 类型的值,int 和 char 可以根据 ASCII 码相互转换. num 为 ptr 的前 num 个字节,size_t 就是

  • 浅析C++中memset,memcpy,strcpy的区别

    复制代码 代码如下: #include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h> //memcpy:按字节复制原型:extern void* memcpy(void *dest,void *src,unsigned int count)//功能:由src所指内存区域复制count个字节到dest所指的内存区域://同strcpyvoid *memcpy_su(void

  • 基于memset()函数的深入理解

    今天写软件工程大作业,调了半天的bug,原来是对memset函数认识不到位造成的.int max[teachRelationNum];memset(max,0,sizeof(max));注意啊,可以使用sizeof(max),也可以使用 sizeof(int)*teachRelationNum,不可以直接使用 teachRelationNum,来初始化!一般情况下,可以这样使用:memset(max,0,sizeof(max));memset(max,-1,sizeof(max));memset

  • memset函数的使用分析

    1.void *memset(void *s,int c,size_t n)总的作用:将已开辟内存空间 s 的首 n 个字节的值设为值 c.2.例子 复制代码 代码如下: #includevoid main(){char *s="Golden Global View";clrscr();memset(s,'G',6);printf("%s",s);getchar();return 0;} 3.memset() 函数常用于内存空间初始化.如: 复制代码 代码如下: c

  • 详解C语言中的memset()函数

    C语言memset()函数:将内存的前n个字节设置为特定的值 头文件: #include <string.h> memset() 函数用来将指定内存的前n个字节设置为特定的值,其原型为: void * memset( void * ptr, int value, size_t num ); 参数说明: ptr 为要操作的内存的指针. value 为要设置的值.你既可以向 value 传递 int 类型的值,也可以传递 char 类型的值,int 和 char 可以根据 ASCII 码相互转换.

  • 详解C语言中return返回函数局部变量的问题

    目录 return返回栈区局部变量的指针 return返回栈区局部的临时变量 return只读数据段和static数据 在计算机中,释放空间并不需要将空间中的内容全部置成0或者1,而是只要设置这一块空间的数据无效即可.比如在下载文件时需要花很长时间,但是删除文件却只要几秒钟,这是因为操作系统只是把文件标识(文件头链接)删掉了,文件原文还保留着,我们没了文件标识就找不到这个文件了.所以删除后的文件,还可以用特殊的办法被找回来. 这也就意味着,当函数结束调用的时候,函数中的局部变量实际上还是在的,只

  • 详解C语言中的wait()函数和waitpid()函数

    C语言wait()函数:结束(中断)进程函数(常用) 头文件: #include <sys/types.h> #include <sys/wait.h> 定义函数: pid_t wait (int * status); 函数说明:wait()会暂时停止目前进程的执行, 直到有信号来到或子进程结束. 如果在调用wait()时子进程已经结束, 则wait()会立即返回子进程结束状态值. 子进程的结束状态值会由参数status 返回, 而子进程的进程识别码也会一快返回. 如果不在意结束状

  • 详解C语言中的ttyname()函数和isatty()函数的用法

    C语言ttyname()函数:返回一终端机名称 头文件: #include <unistd.h> 定义函数: char * ttyname(int desc); 函数说明:如果参数desc 所代表的文件描述词为一终端机, 则会将此终端机名称由一字符串指针返回, 否则返回NULL. 返回值:如果成功则返回指向终端机名称的字符串指针, 有错误情况发生时则返回NULL. 范例 #include <unistd.h> #include <sys/types.h> #includ

  • 详解C语言中的fopen()函数和fdopen()函数

    C语言fopen()函数:打开一个文件并返回文件指针 头文件: #include <stdio.h> fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为: FILE * fopen(const char * path, const char * mode); [参数]path为包含了路径的文件名,mode为文件打开方式. mode有以下几种方式: 在POSIX 系统,包含Linux 下都会忽略 b 字符.由fopen()所建立的新文件会具有S_IRUSR|S_IWUSR|S_I

  • 详解C语言中的getgrgid()函数和getgrnam()函数

    C语言getgrgid()函数:从组文件中取得指定gid的数据 头文件: #include <grp.h> #include <sys/types.h> 定义函数: strcut group * getgrgid(gid_t gid); 函数说明:getgrgid()用来依参数gid 指定的组识别码逐一搜索组文件, 找到时便将该组的数据以group 结构返回. 返回值:返回 group 结构数据, 如果返回NULL 则表示已无数据, 或有错误发生. 范例 /* 取得gid=3 的组

  • 详解C语言中的rename()函数和remove()函数的使用方法

    C语言rename()函数:重命名文件或目录 头文件: #include <stdio.h> 函数rename()用于重命名文件.改变文件路径或更改目录名称,其原型为 int rename(char * oldname, char * newname); [参数]oldname为旧文件名,newname为新文件名. [返回值]修改文件名成功则返回0,否则返回-1. 重命名文件: 如果newname指定的文件存在,则会被删除. 如果newname与oldname不在一个目录下,则相当于移动文件.

  • 详解C语言中sizeof如何在自定义函数中正常工作

    1.在main函数中,sizeof是可以正常工作的,比如: int main() { int n[5]; printf("input: \n"); int i ; for(i = 0; i < 5; i++) { scanf("%d",n + i); } int len = sizeof(n)/sizeof(n[0]); printf("%d\n",len); return 0; } 2.但是在自定义函数中就不可以了,如下: #includ

  • 详解C语言中return与exit的区别

    详解C语言中return与exit的区别 1,exit用于在程序运行的过程中随时结束程序,exit的参数是返回给OS的.main函数结束时也会隐式地调用exit函数.exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流.关闭所有打开的流并且关闭通过标准I/O函数tmpfile()创建的临时文件.exit是结束一个进程,它将删除进程使用的内存空间,同时把错误信息返回父进程,而return是返回函数值并退出函数 2,return是语言级别的,它

  • 详解 Go 语言中 Map 类型和 Slice 类型的传递

    Map 类型 先看例子 m1: func main() { m := make(map[int]int) mdMap(m) fmt.Println(m) } func mdMap(m map[int]int) { m[1] = 100 m[2] = 200 } 结果是 map[2:200 1:100] 我们再修改如下 m2: func main() { var m map[int]int mdMap(m) fmt.Println(m) } func mdMap(m map[int]int) {

随机推荐