C语言函数:内存函数memcpy()以及实现
Posted srhqwe
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言函数:内存函数memcpy()以及实现相关的知识,希望对你有一定的参考价值。
C语言函数:内存函数memcpy()
引言:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
int main()
int arr1[20] = 1,2,3,4,5,6,7,8,9 ;
int arr2[20] = 0 ;
strcpy(arr2, arr1);
return 0;
strcpy函数:C语言函数:字符串函数及模拟实现strlen() 、strcpy()、 strcat()_srhqwe的博客-CSDN博客
以上代码,如果用strcpy()函数,想将arr1拷贝到arr2中,要明白strcpy()是字符串拷贝函数,这样使用strcpy()会出现问题:
类型不一样arr1和arr2是int类型,strcpy只接收char*类型。如果强行将arr1内容拷贝到arr2中,当是小端存储时,strcpy()访问完一个字节01后,当要访问第二个字节00时,发现00是ASCII码值为0,strcpy会认为这是\\0,然后停止向后继续拷贝。最后arr2只拷贝了01过去,arr2的则变成了0.
因为strcpy不能将arr1拷贝到arr2,因此就急需一个函数是针对内存块进行拷贝的。只要你是针对内存块拷贝,无论你是何种类型,何种数据,都可以进行拷贝:
memcpy()函数:
头文件:#include <string.h>
参数:
函数类型是void*指针,说明返回的是任何类型指针的destination。
destination和source与strcpy()一样,只是类型变成了void*
size_t num是最关键的,意思是:从destination中拷贝num个字节到source中,
函数使用:
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
int main()
int arr1[10] = 1,2,3,4,5,6,7,8,9,10 ;
int arr2[10] = 0 ;
memcpy(arr2, arr1,20);
return 0;
此时要将arr1中的1,2,3,4,5拷贝到arr2中,一个int是4字节,5个int就是20字节,因此num传入20,结果:
其中20可以使用sizeof(int),算出一个int大小,再x上5,也可以得到20
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
int main()
int arr1[10] = 1,2,3,4,5,6,7,8,9,10 ;
int arr2[10] = 0 ;
memcpy(arr2, arr1,5*sizeof(int));
return 0;
memcpy函数的实现:
创建:void* my_memcpy(void* dest, const void* sour, size_t num)
size_t == (unsigned)int----------只有正数
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
void* my_memcpy(void* dest, const void* sour, size_t num)
for (int i = 0; i < num; i++)
*((char*)dest + i) = *((char*)sour+i);
return dest;
int main()
int arr1[10] = 1,2,3,4,5,6,7,8,9,10 ;
int arr2[10] = 0 ;
my_memcpy(arr2, arr1,5*sizeof(int));
return 0;
因为dest是void*,不能通过+1或++之类的操作符对他进行改变。因为计算机并不知道void*+1跳多少字节。如果+1首先代码行就会变成红色(出错)
这里将dest和sour强制类型转换成char*,那么每次+i就能移动一个字节。可以保证每个字节都做出了改变。
如果强制类型转换成int或其他的类型,这个函数就有了局限性。+1就跳4字节。那么中间这四个字节没有做出改变,如果此时传入char类型的数据,那么就会使得内容缺失。
memcpy内存重叠问题:
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
void* my_memcpy(void* dest, const void* sour, size_t num)
for (int i = 0; i < num; i++)
*((char*)dest + i) = *((char*)sour+i);
return dest;
int main()
int arr1[10] = 1,2,3,4,5,6,7,8,9,10 ;
int arr2[10] = 0 ;
my_memcpy(arr1+2, arr1,5*sizeof(int));
return 0;
如以上代码,memcpy函数从arr1拷贝的内容放到了&arr1[2]上。
如果正常此时按照这样拷贝,arr1中就会变成1,2,1,2,3,4,5,8,9,10
但是实际上却是:
显然与预期不符,那么为啥呢?
当从arr1上拿数据放到arr1+2中[3][4]的两个位置变成了1,2;
arr1[3]和arr[4]以及变成了1,2;此时又从这两个地方拿数据放到[5][6],这两个位置也变成了1,2.以此类推。最后得到了1,2,1,2,1,2,1,8,9,10
那么如何才能达到预期的效果呢?
可以使用一个函数:memmove ()
C语言学习内存操作函数之------->memcpy memmove 详解与手动实现
C语言中有时需要对内存空间进行操作,下面详解三个常用的内存操作函数
函数 |
---|
memcpy |
memmove |
一、memcpy
1. memcpy函数简介
memcpy | —————————— |
---|---|
参数 | ( void *destination , const void *source , size_t num) |
返回值 | void * |
作用 | 从source的位置开始向后复制num个字节的数据到destination的位置 |
内存空间可能存储着各种类型的数据,如int,char,double,那么在对内存空间的数据进行操作时,就需要一个“万金油”的参数——void* 类型,void* 类型的变量可以存储不同类型数据的地址;参数size_t的单位为字节,是确认对内存空间操作多少字节的数据
2. memcpy函数的手动实现
通过上图,将数据5 6 7 8 9拷贝至0 1 2 3 4内存空间的后面,以此手动实现memcpy。
int arr1[10] = 0, 1, 2, 3, 4 ;//给定10个内存空间,只存放5个数据,用于拷贝arr2的数据
int arr2[5] = 5, 6, 7, 8, 9,;
void *my_memcpy(void *dest , const void* src ,int num)
my_memcpy(&arr1[5],arr2,sizeof(arr2));//函数参数与memcpy一致
由于参数num已经明确给出拷贝字节数的多少,故可以以1字节为单位,循环拷贝num次即可。
void *my_memcpy(void *dest , const void* src ,int num)
int i = 0;
for (i = 0; i < num; i++)
*((char*)dest + i) = *((char*)src + i);
return dest;
拷贝前后如下图
整体代码:
void *my_memcpy(void *dest , const void* src ,int num)
int i = 0;
for (i = 0; i < num; i++)
*((char*)dest + i) = *((char*)src + i);
return dest;
int main()
int arr1[10] = 0, 1, 2, 3, 4 ;
int arr2[5] = 5, 6, 7, 8, 9,;
my_memcpy(&arr1[5],arr2,sizeof(arr2));
return 0;
mymcpy有一定缺陷,如果source和destination有任何的重叠,拷贝的结果都是未知的。但下文memmove函数很好地弥补了这点缺陷
二、memmove
1. memmove函数简介
memove | —————————— |
---|---|
参数 | (void* destination , const void* source , size_t num) |
返回值 | void * |
作用 | 处理源空间与目标空间出现重叠而无法拷贝的情况 |
拷贝数据时可能会出现下图情况
将0 1 2 3拷贝至2 3 4 5中,由于有重叠内存空间2 3的存在,故涉及到是从0开始拷贝到3结束(从前向后拷贝),还是从3开始拷贝到0结束(从后向前拷贝),达到我们的目的即:0 1 0 1 2 3 6 7 8 9
memmove拷贝顺序 | —————————— |
---|---|
源空间在目标空间之前 | 从源空间最后一个数据向前拷贝 |
源空间在目标空间之后 | 从源空间第一个数据向后拷贝 |
2.memmove函数的手动实现
大体代码与memcpy函数一致,主要解决的是空间重叠问题,故不做过多解释,直接源代码:
void* my_memmove(void *dest, const void*src, int num)
int i = 0;
if (src > dest)
for (i = 0; i < num; i++)
*((char *)dest + i) = *((char*)src + i);
else
for (i = num - 1; i>=0; i--)
*((char*)dest + i) = *((char*)src + i);
return dest;
int main()
int arr[10] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ;
my_memmove(&arr[2], arr, 4 * sizeof(int));
return 0;
memmove处理前后数据变化如下图:
以上即为两个常用的内存操作函数详解。
以上是关于C语言函数:内存函数memcpy()以及实现的主要内容,如果未能解决你的问题,请参考以下文章
C语言学习内存操作函数之------->memcpy memmove 详解与手动实现
C语言学习内存操作函数之------->memcpy memmove 详解与手动实现