1.memcpy的使用和模拟实现
void * memcpy ( void * destination, const void * source, size_t num );
- 这个函数的作用是将source的前num个字节拷贝到destination
- 遇到‘\0’并不会停止
- 如果source与destination有任何重叠,拷贝结果是未定义的
看下面一段代码:
一个整形4个字节,拷贝爱arr2的前20个字节到arr1,即把arr1的前5个整形改为0;
但是如果我传的num并不是4的整数倍可能会出现特殊情况:
这里arr2的首元素是1234,其余全是0。1234的16进制为4D2(内存中的存储看图最右侧)
当运行memcpy后可以看到arr1的首元素的第一个字节被改为D2,转化成10进制正好是210。
或者说传参的两个地址并不是一个类型:
为什么会出现这种情况?:
结论1:memcpy是以字节为单位进行拷贝,尽量不要拿它来给char类型外的数据拷贝。
结论2:memcpy遇到'\0'不会停止
memcpy的模拟实现:
#include<stdio.h>
#include<string.h>
char* my_memcpy(void* dest, const void* src, int num)
{char* str = (char*)dest;while (num--){*((char*)dest) = *((char*)src);dest = (char*)dest+1;src = (char*)src + 1;}return str;
}
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };my_memcpy(arr2, arr1, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}return 0;
}
2.memmove的使用和模拟实现
void * memmove ( void * destination, const void * source, size_t num );
memmove基本同memcpy,但是它们两个的区别是 前者可以拷贝有重叠区域的两块数据;
先看为什么memcpy不能拷贝重叠的内存块:
而memmove很好的解决了这个问题:
具体是怎么个原理呢?
memmove的模拟实现:
#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_memmove(void* dest, const void* src, int num)
{assert(dest && src);char* str = (char*)dest;if (dest <= src){while (num--){*((char*)dest) = *((char*)src);dest = (char*)dest + 1;src = (char*)src + 1;}}else{while (num--){*((char*)dest + num) = *((char*)src + num);}}return str;
}
int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };my_memmove(arr1 + 2, arr1, 20);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}return 0;
}
3.memset函数的使用
void * memset ( void * ptr, int value, size_t num );
memset 顾名思义就是用来设置内存的,以字节为单位
4.memcmp函数的使用
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
- 比较从ptr1与ptr2往后的num个字节。
- 比较的是字母序
返回值:
注:返回值在vs中是1 0 -1