内存操作函数 memcpy, memchr, memcmp, memset, memmove

1. memcpy 与 strcpy

        memcpy() 函数与 strcpy() 函数(9-6 字符串的连接和复制_gltzlike的博客-CSDN博客)用法大致相同。memcpy() 函数将第二个变量的指定数量内存块复制到第一个变量内存块的起始位置,且需要指定复制几个内存块mem 开头的函数都有这个特点,都需要指定操作内存块的数量。(strcpy 函数的操作仅适用于字符串,字符串自带 '\0' 结束标志,不需要指定操作内存块数量)

void TestMemcpy(){
 
  char string1[] = "ABCDE";
  char* string2 = "FGHIJ";
 
  memcpy(string1, string2, 4); // string2 复制 4 个字节到 string1 中
 
  printf("string1: %s\n", string1);  // FGHIE
}

2. memchr 与 strchr

        memchr() 函数与 strchr() 函数(9-4 查找字符与子串_gltzlike的博客-CSDN博客)类似,都是找寻一个字符。区别在于 memchr() 函数在一段内存中查找一个字符,strchr() 函数在一个字符串中查找一个字符。例如代码中 memchr() 可以去 int 类型的数组查找一个字符,虽然结果为 NULL。

void TestMemchr(){
  
  // 从字符串中查找
  char string1[] = "Hello";
  char* temp = memchr(string1, 'l', 5); 
  printf("%s\n", temp);  // llo
 
  // 从数组中查找
  int a[] = {0,1,2,3,4};
  char* temp2 = memchr(a, 48, 5);  // 48 对应的是ASCII码表中的 '0'
  printf("%s\n", temp2);  // (null)
}

3. memcmp 与 strcmp

        memcmp() 函数可以和 strcmp() 函数(9-3 字符串的长度与比较_gltzlike的博客-CSDN博客_比较字符串长度)一样,去比较字符串的大小,但也可以去比较 int 类型的数组大小。但在比较时需注意,一个 int 4 个字节,选择的字节数会影响比较结果

void TestMemcmp(){
 
  // 比较字符串大小
  char *left = "Hello W";
  char *right = "Hello C";
 
  printf("%d\n", memcmp(right, left, 7));     // right<left -1
  printf("%d\n", memcmp(left, right, 7));     // left>right 1
  printf("%d\n", memcmp(left, right, 6));     // left=right 0
 
  // 比较数组大小
  int a[] = {2,2,0,4,5};
  int b[] = {2,2,3,4,5};
  int result = memcmp(a, b, 8);
  printf("a?b: %d\n", result);  // a?b: 0
 
  int result2 = memcmp(a, b, 9);
  printf("a?b: %d\n", result2);  // a?b: -1
}

        如上述代码所示,a 数组和 b 数组比较前八个字节时,a==b,比较第九个字节时才能发现 a<b。原因在于 memcmp() 函数是一个字节位一个字节位进行数组元素比较的,如下图所示,数组中的第三个元素是从第八个字节位开始存储的(0为起点)。

4. memset

        memset() 函数没有与之对应的 string 兄弟,它的功能是将指定数量内存块(字节)的存储值都设置为某一个值。

void TestMemset(){
 
  char *a = malloc(5);  // 请求分配 5 个字节
 
  for (int i = 0; i < 5; ++i) {
    printf("%d, ", a[i]);   // -51, -51, -51, -51, -51,
  }
 
  memset(a, 0, 5); // 将 5 个字节的值设置为 0
  printf("\n");
  for (int i = 0; i < 5; ++i) {
    printf("%d, ", a[i]);  // 0, 0, 0, 0, 0,
  }
 
  free(a);
}

5. memmove

        memmove() 函数与 memcpy() 函数类似,参数一致,执行结果在 msvc 和 gcc 编译器下相同。memmove() 也是将第二个变量的内存块复制到第一块内存的起始地址,唯一的不同是 memmove() 函数更适用于第一个变量和第二个变量的内存区域有重叠

void TestMemmove(){
 
  char str[] = "memmove can be very useful......";
  memmove (str+20,str+15,11);
  puts (str);  // memmove can be very very useful.
 
  char str2[] = "memmove can be very useful......";
  memcpy(str2+20,str2+15,11);
  puts(str2);  // memmove can be very very useful.
}

图出处:http://c.biancheng.net/cpp/html/156.html

        如上图所示,当第一个变量(userful.....)和第二个变量(very useful)的内存块有重叠时,memmove() 函数可以将第二个变量的值先放入缓冲区,然后再对第一个变量的值进行覆盖。这样做的好处是,以第 20 位的 u 为例,防止 u 没有复制到 25 位时,值就被改写了。这里的矛盾在于,第15位的 v 要复制到第20位 u,第20位 u 要复制到第25位 i,有个前后顺序的问题,应该先将 20位的 u 复制到 25位的 i 上,再把 15 位的 v 复制到 20 位 u 上。

1、memcpy和memmove

memcpy()--拷贝内存内容

头文件:#include<string.h>或#include<cstring>

定义函数:void *memcpy(void *dst,const void *src,size_t n)

函数说明:memcpy用来拷贝src所指的内存内容前n个字节到dst所指的内存地址上。与strcpy不同的是,memcpy会完成的复制n个字节,不会遇到字符串结束'\0'而结束(strncpy待会验证)。

返回值:返回指向dst的指针。

附加说明:指src和dst所指的内存区域不可重叠

重叠实例:

 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 int main()
 5 {
 6     int a[10] = {0};
 7     for (int i = 0; i < 10; i++)
 8         a[i] = i;
 9     memcpy(&a[4],a,sizeof(int)*6);
10     //memmove(&a[4], a, sizeof(int) * 6);
11     for (int i = 0; i < 10; i++)
12         cout << a[i];
13     getchar();
14     return 0;
15 }

会输出0123012301,但是vs会输出和memmove一样的结果0123012345,原因是对src进行了保护,不允许更改。

2、memmove()--拷贝内存内容

表头文件:#include<string.h>或#include<cstring>

定义函数:void* memmove(void* dst,const void* src,size_t n)

函数说明:memmove()与memcpy()一样都是用来拷贝src所指的内存前n个字节到dst所指的内存上。

不同的是,当src和dest所指的内存区域重叠时,memmove仍然可以正确的处理,不过执行效率上会比memcpy略慢。

返回值:返回值指向dst的指针。附加说明:指针src和dst所指的内存区域可以重叠。

3、memset()--设置内存内容

表头文件:#include<memory.h>  #include<string.h>

函数说明:memset是C的库函数,将s所指向的某一块内存中的前n个字节全部设置成ch制定的ASCII值,块的大小由第三个参数制定,这个函数通常为新申请的内存做初始化工作。

定义函数:void* memset(void *s,int ch,size_t n)

函数解释:将s中前n个字节用ch替换并返回s。

作用:在一段内存块中填充某个给定的值,他是对较大的结构体或数组进行清零操作的一种最快方法。

返回值:指向s的指针

上面的例子可以改一下

1     int a[10] = {0};
2     memset(a,0,10);

4、memchr()--查找内存内容

表头文件:#include<string.h>

函数说明:从buf所指内存区的前count个字节查找字符ch,当第一次遇到字符ch时停止查找。如果成功,返回指向字符ch的指针;否则返回null

定义函数:extern void* memchr(const void* buf,int ch,size_t count)

代码实现

 1 #include<iostream>
 2 #include<string.h>
 3 using namespace std;
 4 int main()
 5 {
 6     char a[] = "nihao jingliming";
 7     void *p;
 8     p = memchr(a,'j',sizeof(a));
 9     if (p)
10         cout << "has found:" << *((char*)p) << endl;
11     else
12         cout << "not found" << endl;
13     getchar();
14     return 0;
15 }

---------------------
作者:gltzlike
来源:CSDN
原文:https://blog.csdn.net/gltzlike/article/details/119459259

https://www.cnblogs.com/jingliming/p/4737409.html
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值