1. memcpy使用和模拟实现
void * memcpy ( void * destination, const void * source, size_t num );
1. memcpy函数将 source 指向的位置开始向后num个字节的数据直接复制到 destination 指向的内存块。
2. 该函数不检查source中是否有任何终止 null 字符 - 它始终精确地复制 num 字节。
3. 如果source和destination有任何的重叠,复制的结果都是未定义的。
4. 为避免溢出,目标参数和源参数所指向的数组的大小应至少为数字字节。
//memcpy函数的模拟实现
#include<stdio.h>
void* my_memcpy(void* dest, void* sour, size_t num)
{
void* ret = dest;
while (num--)
{
*(char*)dest = *(char*)sour;
(char*)dest=(char*)dest+1;
(char*)sour=(char*)sour+1;
}
return ret;
}
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memcpy(arr1, arr2, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
2. memmove使用和模拟实现
void * memmove ( void * destination, const void * source, size_t num );
1. 和memcpy函数的差别就是memmove函数处理的源内存块和目标内存块可以重叠。
2. 如果原空间和目标空间出现重叠,就得使用memmove函数处理。
这里应注意覆盖拷贝的一个问题,那就是未被拷贝到目标空间的元素已发生改变,如下图:
那么如何规避这种情况呢?
我们可以改变拷贝的顺序使未被拷贝的元素保持原样,具体操作如下:
情况1:destination和source未发生重叠:逆序或顺序都可以
情况2:destination和source重叠:
1. source在destition之前,以source的逆序拷贝到destination中
2. source在destition之后,以source的顺序拷贝到destination中
memmove的模拟实现:
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* sour, size_t num)
{
assert(dest && sour);
void* ret = dest;
//dest在sour之后重叠----从前拷贝到后
if(dest<sour)
while (num--)
{
*(char*)dest = *(char*)sour;
(char*)dest=(char*)dest+1;
(char*)sour = (char*)sour + 1;
}
//dest在sour之前重叠或者不重叠----从后拷贝到前
//不重叠:(char*)dest>=(char*)sour+num
else
while (num--)
{
*((char*)dest + num )= *((char*)sour + num);//将void*类型的指针sour强制类型转换
//为char*类型,加上num跳过num个字节,对其解引用得到dest内存块中的第num个字节的内容
}
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr + 2, arr, 5 * sizeof(int));
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[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 );
1. 将 ptr1 指向的内存块的第一个 num 字节与 ptr2 指向的第一个 num 字节进行比较,如果它们都匹配,则返回 0,或者返回一个与 0 不同的值,表示如果它们不匹配,则哪个值更大,与 strcmp 不同,该函数在找到 null 字符后不会停止比较。
2. 返回值:
返回一个整数值,该值指示内存块的内容之间的关系:
返回值 | 表明 |
---|---|
<0 | 在两个内存块中不匹配的第一个字节在 PTR1 中的值低于 PTR2 中的值(如果计算为无符号字符值) |
0 | 两个内存块的内容相等 |
>0 | 在两个内存块中不匹配的第一个字节在 PTR1 中的值大于 PTR2 中的值(如果计算为无符号字符值) |