memcpy、memmove、memset、memchr、memcmp、strstr详解
2015-08-17 18:52
489 查看
第一部分 综述
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个字节,不会遇到字符串结束'\0'而结束(strncpy待会验证)。
返回值:返回指向dst的指针。
附加说明:指src和dst所指的内存区域不可重叠
重叠实例:
#include<iostream> #include<string.h> using namespace std; int main() { int a[10] = {0}; for (int i = 0; i < 10; i++) a[i] = i; memcpy(&a[4],a,sizeof(int)*6); //memmove(&a[4], a, sizeof(int) * 6); for (int i = 0; i < 10; i++) cout << a[i]; getchar(); return 0; }
会输出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的指针
上面的例子可以改一下
int a[10] = {0}; 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)
代码实现
#include<iostream> #include<string.h> using namespace std; int main() { char a[] = "nihao jingliming"; void *p; p = memchr(a,'j',sizeof(a)); if (p) cout << "has found:" << *((char*)p) << endl; else cout << "not found" << endl; getchar(); return 0; }
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
函数说明:该函数是按字节进行比较的
#include<iostream> #include<string.h> using namespace std; int main() { char a[] = "nihao jingliming"; char b[] = "nihao xiaoming"; int r=memcmp(a,b,strlen(a)); if (r>0) cout << "a is big" << endl; else if (r < 0) cout << "b is big" << endl; else cout << "same" << endl; getchar(); return 0; }
第三部分 实现
memcpy和memmove
linux内核版/** * memcpy - Copy one area of memory to another * @dest: Where to copy to * @src: Where to copy from * @count: The size of the area. * * You should not use this function to access IO space, use memcpy_toio() * or memcpy_fromio() instead. */ void * memcpy(void * dest,const void *src,size_t count) { char *tmp = (char *) dest, *s = (char *) src; while (count--) *tmp++ = *s++; return dest; }
/* Normally compiler builtins are used, but sometimes the compiler calls out of line code. Based on asm-i386/string.h. */ #define _STRING_C #include <linux/string.h> #undef memmove void *memmove(void * dest,const void *src,size_t count) { if (dest < src) { __inline_memcpy(dest,src,count); } else { char *p = (char *) dest + count; char *s = (char *) src + count; while (count--) *--p = *--s; } return dest; }
window版
void * __cdecl memcpy (void * dst, const void * src, size_t count) { void * ret = dst; /* * copy from lower addresses to higher addresses */ while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } return(ret); }
void * __cdecl memmove (void * dst, const void * src, size_t count) { void * ret = dst; if (dst <= src || (char *)dst >= ((char *)src + count)) { /* * Non-Overlapping Buffers * copy from lower addresses to higher addresses */ while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } } else { /* * Overlapping Buffers * copy from higher addresses to lower addresses */ dst = (char *)dst + count - 1; src = (char *)src + count - 1; while (count--) { *(char *)dst = *(char *)src; dst = (char *)dst - 1; src = (char *)src - 1; } } return(ret); }
windows写的就是分析的更详细,效率更快。
memset
void *(memset) (void *s,int c,size_t n) { const unsigned char uc = c; unsigned char *su; for(su = s;0 < n;++su,--n) *su = uc; return s; }
memchr
void *memchr (const void *ptr, int value, int num) { if (ptr == NULL) { perror("ptr"); return NULL; } char * p = (char *)ptr; while (num--) { if (*p != (char)value) p++; else return p; } return NULL; }
memcmp
/* 因为类型可以为任意,所以形参应为void * * 相等则返回0,否则不为0 */ int my_memcmp(const void *s1,const void *s2,size_t count) { int res = 0; const unsigned char *p1 =(const unsigned char *)s1;//注意是unsigned char * const unsigned char *p2 =(const unsigned char *)s2; for(p1 ,p2;count > 0;p1++,p2++,count--) if((res =*p1 - *p2) != 0) //不相当则结束比较 break; return res; }
ststr实现
char* strstr(const char *s1, const char *s2) { int n; if (*s2) { while (*s1) { for (n=0; *(s1 + n) == *(s2 + n); n++) { if (!*(s2 + n + 1)) return (char *)s1; } s1++; } return NULL; } else return (char *)s1; }