zoukankan      html  css  js  c++  java
  • memcpy、memmove、memset、memchr、memcmp、strstr详解

    第一部分  综述

    memcpy、memmove、memset、memchr、memcmp都是C语言中的库函数,在头文件string.h中。memcpy和memmove的作用是拷贝一定长度的内存的内容,memset用于缓冲区的填充工作,memchr用于字符的查找工作,memcmp用于比较内存中缓冲区的大小。

    第二部分   介绍

    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个字节,不会遇到字符串结束''而结束(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 }

    5、memcmp()--内存比较

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

    函数原型:int memcmp(const void* buf1,const void* buf2,unsigned int count)

    函数描述:比较buf1和buf2的前count个字节

    返回值:当buf1<buf2时,返回值<0

        当buf1==buf2时,返回值=0

        当buf1>buf2时,返回值>0

    函数说明:该函数是按字节进行比较的

     1 #include<iostream>
     2 #include<string.h>
     3 using namespace std;
     4 int main()
     5 {
     6     char a[] = "nihao jingliming"; 
     7     char b[] = "nihao xiaoming";
     8     int r=memcmp(a,b,strlen(a));
     9     if (r>0)
    10         cout << "a is big" << endl;
    11     else if (r < 0)
    12         cout << "b is big" << endl;
    13     else
    14         cout << "same" << endl;
    15     getchar();
    16     return 0;
    17 }

     第三部分  实现

    memcpy和memmove

    linux内核版

     1 /**
     2  * memcpy - Copy one area of memory to another
     3  * @dest: Where to copy to
     4  * @src: Where to copy from
     5  * @count: The size of the area.
     6  *
     7  * You should not use this function to access IO space, use memcpy_toio()
     8  * or memcpy_fromio() instead.
     9  */
    10 void * memcpy(void * dest,const void *src,size_t count)
    11 {
    12     char *tmp = (char *) dest, *s = (char *) src;
    13     while (count--)
    14         *tmp++ = *s++;
    15     return dest;
    16 }
     1 /* Normally compiler builtins are used, but sometimes the compiler calls out
     2    of line code. Based on asm-i386/string.h.
     3  */
     4 #define _STRING_C
     5 #include <linux/string.h>
     6 #undef memmove
     7 void *memmove(void * dest,const void *src,size_t count)
     8 {
     9     if (dest < src) { 
    10         __inline_memcpy(dest,src,count);
    11     } else {
    12         char *p = (char *) dest + count;
    13         char *s = (char *) src + count;
    14         while (count--)
    15             *--p = *--s;
    16     }
    17     return dest;
    18 } 

    window版

     1 void * __cdecl memcpy (void * dst, const void * src, size_t count)
     2 {
     3         void * ret = dst;
     4 
     5         /*
     6          * copy from lower addresses to higher addresses
     7          */
     8         while (count--) {
     9                 *(char *)dst = *(char *)src;
    10                 dst = (char *)dst + 1;
    11                 src = (char *)src + 1;
    12         }
    13 
    14         return(ret);
    15 }
     1 void * __cdecl memmove (void * dst, const void * src, size_t count)
     2 {
     3         void * ret = dst;
     4 
     5         if (dst <= src || (char *)dst >= ((char *)src + count)) {
     6                 /*
     7                  * Non-Overlapping Buffers
     8                  * copy from lower addresses to higher addresses
     9                  */
    10                 while (count--) {
    11                         *(char *)dst = *(char *)src;
    12                         dst = (char *)dst + 1;
    13                         src = (char *)src + 1;
    14                 }
    15         }
    16         else {
    17                 /*
    18                  * Overlapping Buffers
    19                  * copy from higher addresses to lower addresses
    20                  */
    21                 dst = (char *)dst + count - 1;
    22                 src = (char *)src + count - 1;
    23 
    24                 while (count--) {
    25                         *(char *)dst = *(char *)src;
    26                         dst = (char *)dst - 1;
    27                         src = (char *)src - 1;
    28                 }
    29         }
    30 
    31         return(ret);
    32 }

    windows写的就是分析的更详细,效率更快。

    memset

    1 void *(memset) (void *s,int c,size_t n)
    2 {
    3     const unsigned char uc = c;
    4     unsigned char *su;
    5     for(su = s;0 < n;++su,--n)
    6         *su = uc;
    7     return s;
    8 }

    memchr

     1 void *memchr (const void *ptr, int value, int num)
     2 {
     3 if (ptr == NULL)
     4 {
     5 perror("ptr");
     6 return NULL;
     7 }
     8 char * p = (char *)ptr;
     9 while (num--)
    10 {
    11 if (*p != (char)value)
    12 p++;
    13 else
    14 return p;
    15 }
    16 
    17 return NULL;
    18 }

    memcmp

     1 /*  因为类型可以为任意,所以形参应为void * 
     2  *  相等则返回0,否则不为0 
     3  */  
     4 int my_memcmp(const void *s1,const void *s2,size_t count)  
     5 {  
     6     int res = 0;  
     7     const unsigned char *p1 =(const unsigned char *)s1;//注意是unsigned char *  
     8     const unsigned char *p2 =(const unsigned char *)s2;   
     9     for(p1 ,p2;count > 0;p1++,p2++,count--)  
    10         if((res =*p1 - *p2) != 0)   //不相当则结束比较  
    11             break;  
    12     return res;  
    13 }  

     ststr实现

     1 char* strstr(const char *s1, const char *s2)  
     2 {  
     3     int n;  
     4     if (*s2)  
     5     {  
     6         while (*s1)  
     7         {  
     8             for (n=0; *(s1 + n) == *(s2 + n); n++)  
     9             {  
    10                 if (!*(s2 + n + 1))  
    11                     return (char *)s1;  
    12             }  
    13             s1++;  
    14         }  
    15         return NULL;  
    16     }  
    17     else  
    18         return (char *)s1;  
    19 }  
  • 相关阅读:
    html5实现GIF图效果
    响应式网页设计简单入门(强烈推薦!!!!)
    form表单提交和ajax表单提交,关于移动端如何通过软键盘上的【搜索】和【前进】进行提交操作
    【JavaScript】Write和Writeln的区别
    HTML表格中各元素标签的位置对style属性有效性的影响
    HTML textarea 莫名其妙出现几个空格的原因
    PHP 正则匹配手机号
    极简主义法编写JavaScript类
    jQuery on绑定事件
    jQuery ajax() 参数,回调函数,数据类型,发送数据到服务器,高级选项
  • 原文地址:https://www.cnblogs.com/jingliming/p/4737409.html
Copyright © 2011-2022 走看看