本篇将会将c语言中内存函数的使用以及模拟实现,内存函数有:memmvoe、memcpy、memcmp、memmove,这几个函数。
以下给出来自cplusplus网站对于memcpy函数的解释:
其中需要传入的参数包括目标地址,源地址以及字节数num,这个函数的作用是将源地址的内存拷贝num个字节到目标地址中去,注意:这个函数在遇到\0是不会停下来的,另外这个函数进行地址复制的时候,如果出现源地址与目标地址重叠,那么对于结构是未定的,所以这函数只要求实现非重叠地址的拷贝。
传入参数源地址和目的地址是void*类型是因为,这个函数用于任何形式的字节的拷贝,所以会接受来自各种类型的参数,所以将源地址和目标地址设置为void*类型。
以下为基本用法:
以上的操作实现将arr1数组的前五个元素拷贝到arr2,实际上是字节内存的拷贝,一个字节一个字节的拷贝,以下将实现这个过程。
以下为memcpy的模拟实现:
#include
#include
void* my_memcpy(void* destination, const void* source,size_t num) {
assert(destination && source);
void* ret = destination;
while (num--) {
*(char*)destination = *(char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
return ret;
}
测试结果:
以下为来自cplusplus网站的官方网站对memmove的原理:
memmove传入的参数,返回类型与memcpy一致,作用也与memcpy很相近,但是有一点不同,对于memove,处理的是存在内存重叠的情况,而对于memcpy处理的是内存未重叠的情况,以下为应用举例:
如上图,我们将arr1中的前五个元素拷贝到第四~第八个元素,在同一个数组之间进行拷贝,以下为该函数的模拟实现。
以下为memmove的模拟实现:
#include
#include
void* my_memmove(void* destination, const void* source, size_t num) {
void* ret = destination;
//目标地址在源地址的左边,从前向后进行拷贝
if (destination < source) {
while (num--) {
*(char*)destination = *(char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
}
//目标地址在源地址的右边,从后向前拷贝
else {
while (num--) {
*((char*)destination + num) = *((char*)source+num);
}
}
return ret;
}
测试结果:
1.目标地址在源地址的右边:
2.目标地址在源地址的左边:
测试结果如上,现在来解释为什么需要对目标地址与源地址的左右进行区分,如下图:
所以我们需要对地址位置进行区分,当然,当地址没有重叠时,我们从前往后还是从后往前拷贝都可以。
以下是来自cplusplus网站对memset函数的解释:
memset是用来设置内存的,将内存的值以字节为单位设置成想要的内容,以下为应用举例:
将前六个字节全部设置为自己输入的字符,原理较简单,以下来实现这个函数:
#include
#include
void* my_memset(void* destination, int value, size_t num) {
assert(destination);
void* ret = destination;
while (num--){
*(char*)destination =(char)value;
destination = (char*)destination + 1;
}
}
测试结果:
以下为来自cplusplus网站对memcmp函数的解释:
⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节。一个字节一个字节开始对比,若对应字节的值相同,则开始比较后一个字节,若不相同,ptr1字节大于ptr2时,返回大于0的数,反之,返回小于0的数。比较完都是相等时,则直接返回0;以下为应用举例:
如比较的为字符,则比较相应的ASCII码值,以下将模拟实现该函数。
以下为该函数的模拟实现代码。
#include
#include
int my_memcmp(const void* ptr1, const void* ptr2, size_t num) {
assert(ptr1 && ptr2);
while (num--) {
if (*(char*)ptr1 != *(char*)ptr2) {
return *(char*)ptr1 - *(char*)ptr2;
}
ptr1 = (char*)ptr1 + 1;
ptr2 = (char*)ptr2 + 1;
}
return 0;
}
测试结果: