1.memcpy函数的使用和模拟实现
下面是memcpy函数的原型:
void * memcpy(void* dest, const void* src, size_t num)
要点:
1.memcpy函数从src位置开始向后复制num个字节的数据到dest指向的内存位置。
2.这个函数在遇到'\0'的情况下并不会停下。
3.如果dest和src存在内存冲重叠的情况时不能使用此函数进行复制。
4.处理内存重叠情况下的内存复制使用memmove函数,下文会具体讲到。
但是在VS2022的编译环境下,memcpy在处理重叠内存数据时是不会出现问题的,但在其他编译器上面不一定能够实现;
下面是memcpy函数的使用实例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,7,8,9 };
int arr2[20] = { 0 };
memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
这段代码的运行结果如下图所示:
这个函数是按照字节的方式来进行内存的复制的,复制20个字节就能成功的复制五个整型元素。
下面我们来实现模拟实现一下这个函数:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
void* ret = dest;
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,5,6 };
int arr2[20] = { 0 };
my_memcpy(arr2, arr1, 20);
for (int i = 0; i < 5; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
以上代码就是memcpy函数的模拟实现,通过模拟实现我们可以得知memcpy函数的实现原理。
2.memmove函数的使用以及其的模拟实现
下面是memmove函数的原型:
void * memmove(void* dest , const void* src,size_t num)
要点:
1.memmove函数和memcpy函数的区别就是memmove函数能够处理源内存块和目标内存块重叠的情况。
2.如果源内存块和目标内存块重叠就要使用memmove函数进行处理。
下面是memmove函数使用的实例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
memmove(arr + 2, arr, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
下图是这段代码的运行结果:
可以看出这个函数是能够正确执行任务的。
下面我们来看下这个函数的模拟实现:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
void* ret = dest;
if (dest <= src || (char*)dest >= (char*)src + num)
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,7,8,9,0 };
int* ret = my_memmove(arr1 + 2, arr1, 20);
for (int i = 0; i < 5; i++)
{
printf("%d ", ret[i]);
}
return 0;
}
可以看出这个函数的模拟实现与memcpy有相似之处但是memmove的模拟实现增加了一些细节。
3.memset函数的使用
下面是memset函数的原型:
void * memset (void * ptr, int value, size_t num)
这个函数的作用是将ptr指向的前num个字节的内容设置成value。
memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容
下面的代码是memset使用的实例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = "hello";
memset(str, 'x', 5);
printf(str);
return 0;
}
下图是代码运行结果:
注:memset函数是通过字节设置的不是以类型设置的。
4.memcmp函数的使用
函数的原型如下:
int memcmp(const ovid* ptr1,const void* ptr2,size_t num)
memcmp的作用是比较从ptr1和ptr2指向的方向开始,向后的num个字节。
它的返回类型是整数型;
返回值如下图:
从上图可以看出如果ptr1>ptr2则返回大于0的值;
如果ptr1<ptr2则返回小于0的值;
如果ptr1=ptr2则返回等于0的值;
下面的代码是这次的使用实例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "acdgfty";
int ret = memcmp(arr1, arr2, 7);
if (ret > 0)
{
printf("arr1>arr2\n");
}
else if (ret == 0)
{
printf("arr1==arr2\n");
}
else
{
printf("arr1<arr2\n");
}
return 0;
}
下面是运行结果:
那么通过这个结果我们来思考一下memcmp函数怎么进行比较的呢?
其实memcmp函数是通过比较对应位置每个字节里存放的字符的ASCII码值进行比较的。
如果对应位置的ASCII码小于另一个就返回小于0的值,大于就返回大于0的值,否则返回等于0的值。
这篇博客主要介绍了C语言中常见的内存函数的使用以及原理,谢谢各位的阅读。