memory系列函数对比以及实现

  • 文档内容:
    • memcpy、memmove、memccpy说明、比较
    • memcpy(拷贝)实现
    • memset(设置值)实现
    • memmove(拷贝)实现
    • memccpy(拷贝,遇到设定值终止拷贝)实现

  • memcpy()、 memmove()和memccpy()

    • 这三个函数的功能均是将某个内存块复制到另一个内存块。
      前两个函数的区别在于它们处理内存区域重叠(overlapping)的方式不同。
      第三个函数的功能也是复制内存,但是如果遇到某个特定值时立即停止复制。

    • 对于库函数来说,由于没有办法知道传递给他的内存区域的情况,所以应该使用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()的结果就不一定正确了

  • memccpy原型:extern void *memccpy(void *dest, void *src, unsigned char ch, unsigned int count);

    • 功能:由src所指内存区域复制不多于count个字节到dest所指内存区域,如果遇到字符ch则停止复制。
    • 说明:返回指向字符ch后的第一个字符的指针,如果src前n个字节中不存在ch则返回NULL。ch被复制。

memcpy函数

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>




void *   mymemcpy(void * _Dst, const void * _Src, unsigned int _Size)
{
	if (_Dst ==NULL  || _Src==NULL)
	{
		return NULL;
	}
	char * ndest = _Dst;
	char *  src = _Src;//之指针类型转换

	for (int i = 0; i < _Size;i++)//循环拷贝
	{
		ndest[i] = src[i];

	}
	return ndest;
}
void *   mynewmemcpy(void * _Dst, const void * _Src, unsigned int _Size)
{
	if (_Dst == NULL || _Src == NULL)
	{
		return NULL;
	}
	int i = 0;

	for (char *dest = _Dst, *src = _Src  ; i< _Size     ; dest++, src++, i++)
	{
		*dest = *src;//指针法

	}
	return _Dst;//C语言注意必须返回




}



void main()
{
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	int *p=malloc(sizeof(int )*10);
	mynewmemcpy(p, a, 40);
	//第一个是地址,被拷贝进去的内存地址
	//a用于复制的内存首地址,40长度
	for (int i = 0; i < 10;i++)
	{
		printf("\n%d", p[i]);
	}

	char str[1024] = "hello  boygod";
	char *pstr = malloc(sizeof(char)*  (strlen(str) + 1));//分配内存,处理\0+1

	char *pnew=mynewmemcpy(pstr, str, strlen(str)+1);//拷贝\0
	printf("\n%s", pstr);
	printf("\n%s", pnew);//返回值是void*,拷贝成功的地址

	system("pause");
}

memset函数

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>


void *   mymemset(void * _Dst, int _Val, size_t _Size)
{
	if (_Dst ==NULL)
	{
		return NULL;
	}
	for (int i = 0; i < _Size;i++)
	{
		 ( (char*)_Dst) [i] = _Val;//下标法
	}
	return _Dst;
}

void *   mymemsetaddr(void * _Dst, int _Val, size_t _Size)
{
	//((char*)_Dst) + _Size注意类型
	if (_Dst == NULL)
	{
		return NULL;
	}
	for (char *p = _Dst; p < ((char*)_Dst) + _Size;p++)
	{
		*p = _Val;//指针法
	}
	return _Dst;


}

void main()
{

	int a[5] = { 1, 2, 3, 4, 5 };
	double db[5] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
	char str[1024] = "hello world";

	mymemsetaddr(a, 0, 20);
	mymemsetaddr(db, 0, 40);//整数,实数清零

	mymemsetaddr(str,'A', 1023); //填充
	//数据填充
	for (int i = 0; i < 5;i++)
	{
		printf("\n%d,%f", a[i], db[i]);
	}
	printf("%s", str);

	system("pause");

}

memmove(拷贝)实现

#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void *   mymemmove(void * _Dst, const void * _Src, size_t _Size)
{
	if (_Dst ==NULL  || _Src ==NULL)
	{
		return NULL;
	}


	void *psrc = malloc(_Size);//分配内存
	memcpy(psrc, _Src, _Size);//整体拷贝到临时内存
	memcpy(_Dst, psrc, _Size);//临时内存拷贝到
	free(psrc);//释放内存
	return _Dst;

}



void main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int b[5] = {0};
	for (int i = 0; i < 5;i++)
	{
		printf("\n%d,%d", a[i], b[i]);
	}
	mymemmove(b, a, 12);

	for (int i = 0; i < 5; i++)
	{
		printf("\n%d,%d", a[i], b[i]);
	}

	char str1[32] = "abcdefghijklmnopq";
	char str2[32] = "*****************";

	mymemmove(str2, str1, 6);
	printf("\n%s,%s",str1, str2);
	mymemmove(str1+2, str1, 4);

	printf("\n%s,%s", str1, str2);
	system("pause");
} 

memccpy(拷贝,遇到设定值终止拷贝)实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void *  my_memccpy( void * _Dst,  const void * _Src, int _Val,  size_t _MaxCount)
{
	char *dst = _Dst;
	char *src = _Src;//指针转换

	for (int i = 0; i < _MaxCount;i++)
	{
		if ((dst[i] = src[i]) == _Val)//下标法
		{
			break;
		}
	}
}

void *  my_memccpyaddr(void * _Dst, const void * _Src, int _Val, size_t _MaxCount)
{
	char *dst = _Dst;
	char *src = _Src;//指针转换
	int i = 0;
	while (i<_MaxCount)//控制循环次数
	{
		//*dst = *src;//指向的字符赋值
		//if (*dst ==_Val)
		//{
		//	break;
		//}
		//dst++;
		//src++;
		//i++;
		;//指向的字符赋值
		if ((*dst++ = *src++) == _Val)
		{
			break;
		}
		i++;
	}
}




void main()
{
	char str[100] = "i am  wuwei,many girls love me ";

	char *pstr = (char[128]){0};//(char[128]){0}栈上

	my_memccpyaddr(pstr, str, 'g', 30);//往前拷贝30个字符,遇到字符'g'提前终止

	printf("%s", pstr);

	system("pause");
}
posted @ 2016-11-27 14:08  呉语伦比  阅读(1677)  评论(0编辑  收藏  举报