- 文档内容:
- 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");
}