您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: