1.memcpy函数使用
我们之前学过一个函数叫做strcpy是用来拷贝字符串的,今天来学习的函数可以拷贝任意类型数据。
我们可以看到它有三个参数,它的第一个参数也是指向目标空间的指针,第二个参数是指向需要拷贝的数据 。第三个参数是需要拷贝的数据的大小,单位字节。返回值是拷贝后目标空间的首元素地址。头文件为<string.h>。
演示如下:
在这里因为float类型的数据大小为4个字节,所以我们拷贝数据大小就为20,且我们在此处使用%.1f表示打印一位小数。
我们在此拷贝的空间和目标空间不相同,那如果自己拷贝到自己的位置会怎么样呢?
其实,在c语言中我们提供了一个函数是专门用来完成这种重叠空间的问题的。
那就是memmove函数。这个我们待会再说。虽然memcpy在vs上也可以完成重叠空间的情况,但是c语言规定的是menmove就是用来完成重叠空间的情况,所以以后写到这种情况最好用memmove来完成。
注意:
• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
• 这个函数在遇到 '\0' 的时候并不会停下来。
• 如果source和destination有任何的重叠,复制的结果都是未定义的。
2.memcpy的模拟实现
我们在实现strcpy时是使用的char*指针完成一个字节一个字节的搬运,这样就可以满足数据的拷贝,那么我们可以在memcpy中使用这种想法吗?
演示如下:
#include<assert.h>
#include<string.h>
void* my_memcpy(void*p1,void*p2,size_t num)
{
void* pt = p1;
assert(p1);//p1,p2不能为空指针。
assert(p2);
while (num--)//num刚好为字节个数,我们就搬运多少次。
{
*(char*)p1 = *(char*)p2;//void*指针不可以直接解引用
p1 = (char*)p1 + 1;
p2 = (char*)p2 + 1;//void*指针不可以直接加减
}
return pt;
}
int main()
{
float arr[] = { 1.2,1.3,3.4,5.2,2.6 };
float arr1[30] = { 0 };
float*pt=(float*)my_memcpy(arr1, arr, 20);
for (int i=0;i<5;i++)
{
printf("%.1f ", arr1[i]);
}
return 0;
}
那它可以玩成拷贝任务吗?我们运行一下。
3.memmove的使用
它的使用跟memcpy差不多,只是专门运用于重叠空间问题。头文件为<string.h>
演示如下:
4.memmove的模拟实现
void * memmove ( void * dst, const void * src, size_t count)
{
void * ret = dst;
if (dst <= src || (char *)dst >= ((char *)src + count)) {
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
}
else {
dst = (char *)dst + count - 1;
src = (char *)src + count - 1;
while (count--) {
*(char *)dst = *(char *)src;
dst = (char *)dst - 1;
src = (char *)src - 1;
}
}
return(ret);
}
我们在处理这种重叠情况时需要注意是从头开始搬运,还是从尾开始搬运,这都是需要讨论的,什么时候从头搬运,什么时候从后搬运。大家可以看着模拟实现的代码,多思考一下。
5.memset的使用
它是用来设置内存的, 第一个参数是指向想修改的空间,第二个是想修改的内容,第三个就是想修改的大小,单位字节。返回修改后首元素地址。头文件为<string.h>。
演示如下:
字符是以ASCLL码值的方式存入的,所以也可以是int 。
这个函数的模拟实现大家可以尝试一下。
6.memcmp的使用
它与strncmp只有参数的类型不同,其实我们可以理解为memcmp就是strncmp的升级版。
演示如下:
到这里我们就了解到了这些内存函数。
![](https://img-blog.csdnimg.cn/direct/b82452c8b75e440783f07a7b1fe5fbe6.png)