目录:
1.memcpy使用和模拟实现
2.memmove使用和模拟实现
3.memset使用
4.memcmp使用
一.memcpy使用和模拟实现
void * memcpy ( void * destination, const void * source, size_t num );
1.memcpy函数需要传递3个参数,表示从source处开始向后复制num个字节数据到destination处.
2.该函数在遇到‘\0’的时候并不会停下来
3.若是source和destination有任何的重叠,复制结果都是未知的
4.num的单位是字节,即以字节为单位拷贝数据
5.destination is returned.即返回值是拷贝目标的地址
eg:
#include <stdio.h>
#include <string.h>//注意头文件
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };//为arr2初始化足够的空间使arr1能够拷贝进去
memcpy(arr2, arr1, 20);//20指的是20个字节,即五个整形元素
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
这里会不会有小伙伴有疑问,若是自己给自己是否能拷贝?这里就存在了上文提及的内存重叠问题,这就要交给后面的memmove函数啦.
memcpy函数的模拟实现:
void* my_memcpy(void* des,const void* src,size_t,count)
{
void* ret=des;//记录拷贝目标的地址
assert(des&&src);//使传递的地址有效
while(count--)
{
*(char*)des=*(char*)src;
des=(char*)des+1;
src=(char*)src+1;
//为什么要用char*强制转换呢?
//这正是因为memcpy是以字节为单位拷贝数据的
//并且强转是一次性的,所以不能des++或src++
}
return ret;
}
二.memmove使用和模拟实现
void * memmove ( void * destination, const void * source, size_t num );
memmove函数与memcpy函数非常类似,最大的差别就是其处理的源内存块和目标内存块是可以重叠的。
eg:
#include <stdio.h>
#include <string.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr+2, arr, 20);
//这里arr指向的目标空间arr+2与源空间是存在重叠的
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
//1 2 1 2 3 4 5 8 9 10
}
return 0;
}
这个结果你是否预料到?接下来让我们详细分析memmove大概是如何实现的:
当源内存块与目标内存块发生重叠时:
一般来说我们习惯于从前向后拷贝,一般来说利用memmove函数没什么问题,
但是存在下面这种特殊情况情况:
所以,从前向后不行,那从后向前呢?
这样就没问题了,所以由以上不难看出,只要我们分清了什么情况下我们从前向后拷贝,什么时候从后向前拷贝,这样就不难理解memmove函数了。我们可以将所有情况分类:
注意:数组从左向右是由低地址到高地址。(正因如此若是des在src左边就可表示为des<src)
memmove的模拟实现:
这里我们采取第一种划分方式,比较简便:
void* my_memmove(void* des, const void* src, size_t count)
{
void* ret = des;
//前->后
if (des <= src)
{
while (count--)
{
*(char*)des = *(char*)src;
des = (char*)des + 1;
src = (char*)src + 1;
}
}
else
{
//后->前
while (count--)
{
*((char*)des + count* ((char*)src + count);
例如count是20,进入while的时候变成19,初始地址加上偏移量找到src最后一个字节,再将他赋给des
}
}
return ret;
}
三.memset使用
void * memset ( void * ptr, int value, size_t num );
功能:memset是用来设置内存的,将内存中的值以字节为单位设置成想要的内容。
eg:
#include<stdio.h>
#include<string.h>
int main()
{
char str[] = "hello coder!";
memset(str, '*', 5);
printf(str);
return 0;
}
输出结果如下:
memset成功将字符串中前五个字符修改为设置的‘*’,这便是该函数的功能。
四.memcmp使用
int memcmp ( constvoid * ptr1, constvoid * ptr2, size_t num );
1.比较ptr1和ptr2指针指向的位置开始,向后num个字节大小(以ascii值为比较标准)
2.返回值如下:
eg:
#include<stdio.h>
#include<string.h>
int main()
{
char buffer1[] = "UHgabagwijd";
char buffer2[] = "UHGABagwijd";
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;
}
输出结果:'UHgabagwijd' is greater than 'UHGABagwijd'.
这是因为从左向右比较时到第三位a的ascii值大于A的ascii值,从而判定buffer1大于buffer2 。
以上便是对C语言中内存函数的简要介绍和部分模拟实现,有不懂的问题请大家在评论区中提出,不足处还望斧正,感谢。