c语言memcpy源代码,C语言-内存函数的实现(一)之memcpy

C语言中的内存函数有如下这些

memcpy

memmove

memcmp

memset

下面看看memcpy函数

memcpy

我们想想,之前有那个字符串拷贝的函数,即strcpy函数。都有拷贝的函数了,为什么还要这个内存拷贝函数呢?

不能直接用strcpy吗?这是一个好问题,那下面就试试它。

我们准备两个整型数组,分别为arr1和arr2,然后通过strcpy函数把arr1的内容拷贝到arr2中,代码如下

int main()

{

int arr1[] = { 1,2,3,4,5 };

int arr2[5] = { 0 };

// 把arr1的内容拷贝到arr2中

strcpy(arr2, arr1);

return 0;

}

那么这里肯定会有警告,因为类型不同。

直接运行,通过Debug,看内存,可以发现实现不了完整的拷贝,strcpy只拷贝了一个字节

显然,strcpy函数不适用于其他类型的数据拷贝,所以呢,就出现内存拷贝了,使任意类型的数据都能进行拷贝。

老规矩,我们还是看看文档是怎样说的,如下

void * memcpy ( void * destination, const void * source, size_t num );

Copy block of memory

拷贝内存块(拷贝内存数据)

Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.

从source(源内存块位置)直接指向的地方开始复制num个字节的数据到destination指向的内存块位置。

The underlying type of the objects pointed to by both the source and destination pointers are irrelevant for this function; The result is a binary copy of the data.

这句话没看懂,不影响我们学这个。

The function does not check for any terminating null character in source - it always copies exactly num bytes.

这个函数不会检查'\0',不会遇到'\0'就停下来,它就只认识要复制的num个字节数据。

To avoid overflows, the size of the arrays pointed to by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).

为了避免溢出,这两个数组的大小至少为num个字节,而且这两个数组内存位置不应该重叠。

我们从文档中可以看出

参数中除了要复制的字节数num,其他的参数类型基本都是void*,返回值也是void*

该函数是从source的位置开始向后复制num个字节的数据到destination的内存位置。

该函数在遇到'\0' 的时候并不会停下来。

source和destination不能有有任何的重叠。

实现

void* 不能直接解引用,那么如何复制呢?答案是进行类型强转,转换成char*,一个一个字节地复制过去。

一开始得先搞一个指针变量*rest来存储dest,不然目的地址后面发生改变就不知道地址是哪里了。接下来就是主要操作了,把src指向的数据复制给dest,即*(char*)dest = *(char*)src,然后这两个指针都进行偏移,往后走,继续复制,就是循环下去了,直到num个字节复制完就结束,返回目的地址rest。代码如下

断言指针不为空是个好习惯~

void* my_memcpy(void* dest, const void* src, size_t num)

{

assert(dest != NULL);

assert(src != NULL);

void* rest = dest;

// void* 不能直接解引用,那么如何复制呢?

// 给了num个字节,也就是需要复制num个字节

// 那就转换成char*,一个一个字节的复制过去

while (num--)

{

*(char*)dest = *(char*)src;

//++(char*)dest;

//++(char*)src;

((char*)dest)++;

((char*)src)++;

}

return rest;

}

以上,就是memcpy函数的实现。

测试代码

我们就使用下面的测试代码,测试下自己实现的my_memcpy函数,通过Debug来观察内存数据的变化。

struct S

{

char name[20];

int age;

};

int main()

{

int arr1[] = { 1,2,3,4,5 };

int arr2[5] = { 0 };

my_memcpy(arr2, arr1, sizeof(arr1));

struct S arr3[] = { {"LeBron", 36}, {"Kobe", 41} };

struct S arr4[3] = { 0 };

my_memcpy(arr4, arr3, sizeof(arr3));

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分别有三个程序都能使用!1) 进一步理解父子进程之间的关系。 2) 理解内存页面调度的机理。 3) 掌握页面置换算法的实现方法。 4) 通过实验比较不同调度算法的优劣。 5) 培养综合运用所学知识的能力。 页面置换算法是虚拟存储管理实现的关键,通过本次试验理解内存页面调度的机制,在模拟实现FIFO、LRU等经典页面置换算法的基础上,比较各种置换算法的效率及优缺点,从而了解虚拟存储实现的过程。将不同的置换算法放在不同的子进程中加以模拟,培养综合运用所学知识的能力。 2. 内容及要求: 这是一个综合型实验,要求在掌握父子进程并发执行机制和内存页面置换算法的基础上,能综合运用这两方面的知识,自行编制程序。 程序涉及一个父进程和两个子进程。父进程使用rand()函数随机产生若干随机数,经过处理后,存于一数组Acess_Series[]中,作为内存页面访问的序列。两个子进程根据这个访问序列,分别采用FIFO和LRU两种不同的页面置换算法对内存页面进行调度。要求: 1) 每个子进程应能反映出页面置换的过程,并统计页面置换算法的命中或缺页情况。 设缺页的次数为diseffect。总的页面访问次数为total_instruction。 缺页率 = disaffect/total_instruction 命中率 = 1- disaffect/total_instruction 2)将为进程分配的内存页面数mframe 作为程序的参数,通过多次运行程序,说明FIFO算法存在的Belady现象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值