目录
这是一张面试的截图,提到的这两个函数,就是我们本章要学习的内存函数中的两个函数。可以看得出,内存函数还是比较重要的,接下来,我将带大家轻松搞懂C语言中的所有内存函数,展示其内部源代码,帮助大家在面试中也能手撕内存函数!点赞+收藏我们开始。
1. memcpy函数的使用和模拟实现
void * memcpy ( void * destination, const void * source, size_t num );
//destination : 目的地内存的起始地址
//source : 源地址内存的起始地址
//num : 要拷贝的字节个数
我们来铺垫一下,什么是void*呢,这是泛型,可以接受任意数据类型的指针,但使用时必须强转。
这里为什么使用void* 就显然意见了,你不知道要接受什么样的数据类型,那就使用泛型,可以接受所有的数据类型。
那const是什么意思呢,显然我们是将源地址内容放到目的内存中,源内存不需要修改,就用const修饰,避免了误操作。
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
memcpy(arr1, arr2, sizeof(arr2));
size_t sz = sizeof(arr2) / sizeof(arr2[0]);
printf("arr2[] = ");
for (size_t i = 0;i < sz;i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
char c1[6] = { 0 };
char c2[] = "hello";
memcpy(c1,c2,sizeof(c2));
printf("c1[] = %s",c1);
return 0;
}
手撕memcpy函数
void* my_memcpy(void* dest, void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
while(num) //size_t 类型没有负数 !!!
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1; //(char*)dezst++ 程序报错
src = (char*)src + 1;
num--;
}
return ret;
}
这里我们有一个问题,我们可不可以将同一块内存空间中不同位置的内容进行拷贝?例如,将int arr[10] ={1,2,3,4,5,6,7,8,9,10},将1,2,3,4,5放到3,4,5,6,7的位置上呢?
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
显然这不是我们想要的结果,为什么,这是因为内存地址重叠了,我们实现的memmove函数是从前往后拷贝的,3,4,5早就被拷贝成1,2了怎么可能往后拷贝呢。所以可以得出结论,memcpy函数可以处理不重叠的内存之间的数据拷贝。
那如果我们想要将重叠的内存进行数据拷贝,就要使用memmove函数了。
2. memmove函数的使用和模拟实现
void * memmove ( void * destination, const void * source, size_t num );
//destination : 目的地内存的起始地址
//source : 源地址内存的起始地址
//num : 要拷贝的字节个数
我们用memmove函数使用看看我们上面所讲的重叠内存拷贝。
其实我们很容易想出问题所在,既然我们从前往后拷贝有问题,那从后往前呢,这样不是就不会覆盖了吗。其实就这么简单。
但是,我们要注意,不是所有场景都是从前往后,也不是所有场景都是从后往前。
我们要根据不同场景灵活运用,memmove函数就是这么样实现的,它会进行判断。
手撕memmove函数
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (dest > src)
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
else
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
return ret;
}
3. memset函数的使用
void * memset ( void * ptr, int value, size_t num );
memset函数是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "xxxxxxxxxx";
memset(arr, 'h', 5);
printf("%s", arr);
}
4. memcmp函数的使用
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
![](https://i-blog.csdnimg.cn/blog_migrate/c056947fe6c39c98a33a5021ce8ad8f2.png)
#include <stdio.h>
#include <string.h>
int main ()
{
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);
return 0;
}