库函数详解—— 内存函数+模拟实现(部分)
Posted Chaser Feng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了库函数详解—— 内存函数+模拟实现(部分)相关的知识,希望对你有一定的参考价值。
memcpy——内存拷贝1
1.函数功能
memcpy函数是用于拷贝内存块的函数,该函数有三个参数,第一个参数为拷贝的目标地址(void * destination),第二个参数为拷贝源地址(const void * source),因为在拷贝过程中源字符串不会变化,所以参数用 const 修饰,第三个参数为在内存中拷贝的字节数(size_t num),该参数决定了拷贝内存的大小。返回值为拷贝目标的的首地址,因为不清楚拷贝数据的类型,所以返回类型为 void* 型。
对于该函数,要注意:
1.函数memcpy从 source 的位置开始向后复制 num 个字节的数据到destination的内存位置。
2.这个函数在遇到 ‘\\0’ 的时候并不会停下来。
3.如果source和destination有任何的重叠,复制的结果都是未定义的(为拷贝的内容会被覆盖)。
举个栗子:
2.模拟实现
#include<stdio.h>
#include<string.h>
#include<assert.h>
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;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 20);
return 0;
}
memmove——内存拷贝2(可重叠)
1.函数功能
该函数的参数的意义与返回类型同memcpy一样,但是该函数的功能与memcpy略有区别,区别在于:
memmove函数的源内存块和目标内存块是可以重叠的,而memcpy函数的源内存块和目标内存块是不可以重叠的。
所以在拷贝中如果源空间和目标空间出现重叠,就得使用memmove函数处理。
例如:
可以看出,在上述代码中,第一次使用memmove函数时,arr1 < arr+3 ,且拷贝的内存的大小为20字节(即5个整型),即将arr1中的"4 5 6 7 8"序列拷贝到" 1 2 3 4 5"的位置上,两序列有重叠的部分,所以为了拷贝成功,函数是将序列"4 5 6 7 8" 中的内存(每个字节)依次从前向后拷贝(若从后向前拷贝,则原本待拷贝的内容将会被首先拷贝的内容覆盖,从而造成拷贝的序列出错),所以拷贝的过程如下图所示:
而在第二次使用memmove函数时,arr2+2 > arr2,拷贝的内存大小为20字节,为了保证拷贝过程中的合理,第二次拷贝时内存中的序列时从后向前拷贝,如下:
所以从以上两次的拷贝结果可以看出memmove的拷贝机制为:
当 dest < src 时,src 指向的内容拷贝的方式为从前向后拷贝
当 dest > src 时,src 指向的内容拷贝的方式为从后向前拷贝(如上图)
2.模拟实现
根据拷贝机制我们可以模拟实现该函数:
#include<stdio.h>
#include<string.h>
#include<assert.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
{
while (num--)
{
*(((char*)dest) + num) = *(((char*)src) + num);
}
}
return ret;
}
int main()
{
int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1+3, arr1, 20);
return 0;
}
memcmp——内存比较
函数功能:
该函数用来比较两个内存块大小的函数,函数有三个参数,ptr1,ptr2分别为两个待比较的内容的首地址,因为不清楚待比较是内容是什么类型,所以两指针的类型被定义为void* 型,第三个参数为待比较的内存大小(单位字节);与strcmp函数的比较方式类似,但比较的内容不同,该函数会比较从ptr1和ptr2指针开始的num个字节,当ptr1大于ptr2的时候返回一个大于0的数;当prt1等于ptr2的时候返回0;当ptr1小于ptr2的时候返回一个小于0的数。
栗子如下:
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1, 2, 3, 4 };
int arr2[] = { 1, 2, 4, 5 };
int ret1 = memcmp(arr1, arr2, 8);
int ret2 = memcmp(arr1, arr2, 9);
printf("%d %d", ret1, ret2);
return 0;
}
因为arr1,与arr2 在内存中的存储的内存如下图,因为前8个字节的内容相同,所以ret1=0,而第9个字节中的内容不同,所以ret2=-1。
memset——内存设置
函数功能:
该函数是将内存块中的某一部分设置为特定的字符;函数有三个参数,第一个参数是开始设置内存的起始位置,第二个参数是内存将要被设计成的特定字符,第三个参数是从起始位置开始需要设置的内存的字节数。
需要注意的是,该函数设置内存时是一个字节一个字节地进行设置。
举个例子:
再例如:
将字符串 “Hello world!” ,变为 “##### world!” ,代码如下:
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = "Hello world!";
char* ret = memset(str, '#', 5);//字符‘#’传入函数内存的为相应的ASCII值,
//设置的内存大小为5个字节
printf("%s\\n", ret);
return 0;
}
以上是关于库函数详解—— 内存函数+模拟实现(部分)的主要内容,如果未能解决你的问题,请参考以下文章
C语言进阶—— 字符操作函数+内存操作函数详解 (吐血爆肝 !!!)
用python实现模拟登录,突破反爬限制,Selenium库详解(附全部源代码)
用python实现模拟登录,突破反爬限制,Selenium库详解(附全部源代码)
模拟实现部分库函数(strcpy,strcmp,strcat,strstr,memcpy,memmove,memset)