memcpy内存拷贝函数
void* memcpy(void* destination, const void* source, size_t num);
- memcpy函数从source的位置开始向后拷贝num个字节的数据到destination的内存位置
- 这个函数在遇到
\0 的时候并不会停下来
- 如果source和destination有任何的重叠,复制的结果都是未定义的
使用方法:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = { 0 };
char arr2[] = "hello world!";
int arr3[10] = { 0 };
int arr4[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i = 0;
memcpy(arr1, arr2, 12);
memcpy(arr3, arr4, 16);
printf("%s\n", arr1);
for (i = 0; i < 10; i++)
{
printf("%d ", arr3[i]);
}
return 0;
}
输出结果:

如果源头和目的地是同一块内存它进行拷贝的时候会出现覆盖的情况。
如:
#include <stdio.h>
#include <string.h>
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i = 0;
memcpy(arr + 2, arr, 16);
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}

可以看到它并没有如我们预期的输出来输出结果,我们预期的结果应该是:1 2 1 2 3 4 7 8 9 10
可是memcpy拷贝的时候会覆盖,而C语言对memcpy的标准是只要能实现拷贝即可,不考虑同一块内存拷贝会覆盖的情况,这种情况是由另一个函数来处理。
当然有些编译器对memcpy函数的实现是有优化过的,目前我个人知道的编译器是VS它是对memcpy有优化的,如果拷贝的是同一块内存它不会覆盖,而是如预期的那样进行拷贝。
memcpy函数的实现
#include <assert.h>
void* my_memcpy(void* dest, const void* src, unsigned int count)
{
assert(dest && src);//断言
void* temp = dest;//temp保存dest的起始地址
while (count--)
{
*(char*)dest = *(char*)src;//复制src的内容到dest
++(char*)dest;//下一个字节的拷贝
++(char*)src;
}
return temp;//返回dest起始地址
}
void* my_memcpy(void* dest, const void* src, unsigned int count);
参数一:void* dest
- dest设置成空类型,因为空类型可以接收任何大小的数据,但是有一个缺陷它不能自增或者自减,也不能直接解引用因给它空类型是一个没有具体类型,它不知道它能访问多少个字节,所以使用空类型的时候我们需要强制类型转换。
- dest是缓冲区
参数二:void* src
- 它的类型和dest一样不过,它和参数一不同的是它被const保护起来了,因为它只是被复制也就是说我们只是访问它里面的内容并不需要修改它,所以我们就加一个const把它保护起来,防止我们不小心对它进行修改
参数三:unsigned int counst
- counst是我们要修改多少字节的参数,修改是以字节为单位的,它的类型是unsigned int (无符号整整形)也就是说不能出现负数
返回类型:void*
assert(dest && src) 这个是用来保证代码的健壮性,assert() 函数是断言,如果传过来的是空指针,那么就是假因为NULL的值是0,只有两边都为真才不会有提示。
*(char*)dest = *(char*)src 因为是void* 类型所以我们要强制转换才能解引用进行拷贝操作,而我们要操作的是一个字节所以转为字符型指针最合适。
++(char*)dest; 和上面的同理,要强制类型转换才能进行++和–操作。
memmvoe函数
void* memmove(void* destination, const void* source, size_t num);
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理
使用方法:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i = 0;
memmove(arr + 2, arr, 16);
for (i = 0; i < 10; i++)
{
printf("%d ", ar的实现详细讲解的文章就介绍到这了,更多相关C语言内存操作函数的实现内容请搜索社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持社区! |