所属专栏:《C语言进阶》
跟着猪巴戒,一起学习C语言
目录
引言
memcpy
memcpy的使用
memcpy的模拟实现
memmove
memcpy函数不用来处理重叠的内存的数据拷贝:
memmove的模拟实现
总结:
模拟实现代码
memcmp
memset
void * memcpy ( void * destination, const void * source, size_t num )
#include#includeint main(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] = { 0 };memcpy(arr2, arr1, 20);int i = 0;for (i = 0; i < 5; i++){printf("%d ", arr2[i]);}return 0;}
内存函数就是无论是什么类型的数据都可以使用。
void* ,属于通用类型的指针,可以存放任意类型的地址。
assert,断言,保证dest和source不是空指针。
num是需要拷贝的字节数。
通过将地址转化为(char*)的形式,将需要拷贝的内容一个字节一个字节地将它们拷贝,就可以实现各种数据的拷贝。
然后dest转移到下一个字节,source转移到下一个字节,知道拷贝完num个字节算结束。
#include#includevoid* my_memcpy(void* dest, const void* source, size_t num){assert(dest && source);void* start = dest;while (num--){*(char*)dest = *(char*) source;dest = (char*)dest + 1;source = (char*)source + 1;}return start;}
void * memmove ( void * destination, const void * source, size_t num )
将arr1数组改成{1,2,1,2,3,4,5,8,9,10},从第三位元素开始,拷贝自己的第一到第五个元素
#include#includevoid* my_memcpy(void* dest, const void* source, size_t num){assert(dest && source);void* start = dest;while (num--){*(char*)dest = *(char*) source;dest = (char*)dest + 1;source = (char*)source + 1;}return start;}int main(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };my_memcpy(arr1 + 2, arr1, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;}
memcpy在重叠内存拷贝的时候,第三个元素被改成1,第四个元素被改成2,
而第五个元素本来是应该赋值为3的,但是第三个元素已经被改成1了。
第六个元素本来是由第四个元素重新赋值,但是第四个元素被改成了2.
如果说我们要将红色部分拷贝到蓝色部分
从前向后拷贝不行,我们要将红色的部分拷贝到蓝色的部分,先将第一个元素拷贝到第三个元素,红色区域的内存被改变,等到将第三个元素拷贝到第五个元素的时候,第三个元素已经发生改变。
从后向前拷贝,如果我们可以先将第五个元素拷贝到第七个元素,这样红色的三、四、五元素先拷贝完后被改变就可以把数值3,4,5成功传到第五、六、七个元素。
这一次,
从后向前拷贝不行,我们要将红色部分拷贝到蓝色的部分,先将第七个元素拷贝到第五个元素,首先改变了第五个元素的内容,到时候第五个元素还要对第三个元素进行拷贝。
从前向后拷贝,如果我们先将第三个元素拷贝到第一个元素,等轮到第三个元素进行拷贝的时候,第三个元素里的内容已经转出去了,转到第一个元素了,那么第三个元素的内容就可以随便修改了。
为了保证source中的数据在拷贝之前就被修改,
- 当dest在source的右边的时候,采用从后向前的方式
- 当dest在source的左边的时候,采用从前向后的方式
#include#includevoid* my_memmove(void* dest, const void* source, size_t num){assert(dest && source);void* start = dest;if (dest < source){//从前向后while (num--){*(char*)dest = *(char*)source;dest = (char*)dest + 1;source = (char*)source + 1;}}else{//从后向前拷贝while (num--){*((char*)dest + num) = *((char*)source + num);}}return start;}
可以比较任意类型的数据
int memcmp ( const void * ptr1, const void * ptr2, size_t num )
arr1和arr2比较,arr1比arr2小,返回小于0的数值。
int main(){int arr1[] = { 1,2,3,4,5 };int arr2[] = { 1,3,2 };int ret = memcmp(arr1, arr2, 12);printf("%d", ret);return 0;}
void * memset ( void * ptr, int value, size_t num )
#include#includeint main(){char arr[] = "hello world";memset(arr, 'x', 5);printf("%s\n", arr);return 0;}