本文将深入解析C语言中的内存操作函数!
——— 既然选择了,就一定坚持下去
1.memcpy使⽤和模拟实现
1.memcpy的简介
1.参数分析:
void * memcpy ( void * destination, const void * source, size_t num )
参数一:void * destination (指向目标数组,其中要复制内容,类型转换为 void* 类型的指针)
参数二:const void * source(指向要复制数据的源,类型转换为 const void* 类型的指针。)
参数三:size_t num (要复制的字节数)
返回类型:void*
2.功能分析:
将 source 指向的位置的 num 个字节值直接复制到 destination 指向的内存块
3.注意事项:
为避免溢出,指向目标数组和源参数的数组的大小应至少为 num 个字节,并且不应重叠(对于重叠的内存块,memmove 是一种更安全的方法)。
2.memcpy的简单使用
memcpy函数包含在<string.h>这个头文件中,在使用的时候需要包含改头文件进引用,改函数仅仅针对与内存块未重叠时,进行复制操作。
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 5 * sizeof(int));
for (int i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}

3.memcpy的模拟实现
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src); //防止指针为空
void* ret = dest; //由于目标指针会发生改变,保存初始指针
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
2.memmove的使用和模拟实现
1.memmove的简介
1.参数分析:
void * memmove ( void * destination, const void * source, size_t num )
参数一:void * destination (指向目标数组,其中要复制内容,类型转换为 void* 类型的指针)
参数二:const void * source(指向要复制数据的源,类型转换为 const void* 类型的指针。)
参数三:size_t num (要复制的字节数)
返回类型:void*
2.函数功能 :
将 source 指向的位置的 num 个字节值复制到 destination 指向的内存块。复制过程如同使用一个中间缓冲区,允许目标位置和源位置重叠。
3.注意事项:
内存块重叠的理解:例如要将arr数组的前五个(1,2,3,4,5)复制到(3,4,5,6,7),这就会出现内存块的重叠,如果仅仅用memcpy的函数复制方式就会出现赋值异常。
通过memcpy复制五个元素的异常结果。
2.memove的简单使用
通过memmove就可以解决上述问题,代码如下:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("操作前的arr数组\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
memmove(arr + 2, arr, 5 * sizeof(int));
printf("\n操作后的arr数组\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
3.memmove的实现
为了解决memcpy实现不了内存块重叠的问题,我们需要通过实现memmove,来进行处理内存块重叠。
实现思路:
针对于这种情况source的地址小于destination的情况,我们通过正序复制,会导致异常
基于这种情况要将(1,2,3,4,5)正序复制到(3,4,5,6,7)会出现覆盖的情况,那就我们可以通过逆序的方式进行复制,将5->7 4->6 3->5 2->4 1->3 这样就不会出现覆盖的情况。
针对于这种情况source的地址小于destination的情况,我们通过逆序复制,会导致异常
基于这种情况要将(3,4,5,6,7)逆序复制到(1,2,3,4,5)会出现覆盖的情况,所以我们可以通过正序的方式进行复制,将3->1 4->2 5->3 6->4 7->5 这样就不会出现覆盖的情况。
针对不同的情况我们可以通过不一样的复制方式:
①当destination<=source的时候我们可以通过正序的方式进行复制。
②当destination>source的时候我们可以通过逆序的方式进行复制。
#include<stdio.h>
#include<assert.h>
#include<string.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (dest <= src)
{
//按照从前向后的顺序进行拷贝
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
src = (char*)src + num - 1;
dest = (char*)dest + num - 1;
//按照从后向前的顺序进行拷贝
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest - 1;
src = (char*)src - 1;
}
/*
while (num--)
{
*((char*)dest+num) = *((char*)src+num);
}
*/
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("操作前的arr数组\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
my_memmove(arr + 2, arr, 5 * sizeof(int));
printf("\n操作后的arr数组\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
3.memset的使用
1.memset的简介
1.参数分析
void * memset ( void * ptr, int value, size_t num );
参数一:要填充的内存块指针(待赋值的指针)
参数二:要设置的值。该值作为 int 传递,但函数使用该值的无符号字符转换来填充内存块。
参数三:要设置为该值的字节数。
2.函数功能:
将 ptr 指向的内存块的第一个 num 字节设置为指定的值(解释为 unsigned char )。
2.memset的简单使用
#include<stdio.h>
#include<assert.h>
#include<string.h>
int main()
{
char arr1[] = "hello world";
memset(arr1, 'x', 5);
printf("%s\n", arr1);
//int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
//memset(arr2, 1, 10 * sizeof(int));//将每个字节都设置为1
//for (int i = 0; i < 10; i++)
//{
// printf("%d ", arr2[i]);
//}
return 0;
}
4.memcmp的使用
1.memcmp的简介
1.函数参数:
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
参数一:待比较的指针1。
参数二:待比较的指针2
参数三:要比较的字节数
返回值:
2.函数功能:
比较由 ptr1 指向的内存块的前 num 个字节与由 ptr2 指向的内存块的前 num 个字节,如果它们全部匹配则返回零,如果不匹配则返回一个非零值,表示哪个更大。
3.注意事项:
请注意,与 strcmp 不同,该函数在找到空字符后不会停止比较。
2.memcmp的简单使用
void test4()
{
//memcmp 每个字节的比较
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n = memcmp(buffer1, buffer2, sizeof(buffer1));
if (n > 0) printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
else if (n < 0) printf("'%s' is less than '%s'.\n", buffer1, buffer2);
else printf("'%s' is the same as '%s'.\n", buffer1, buffer2);
}
既然看到这里了,就给笔者一个三连吧,谢谢!!!





5660





