一、memcpy库函数的使用和模拟实现
我们可以看到memcpy有3个参数,memcpy的功能是从source指向的内存空间的起始位置取num个字节的内容复制到destination指针指向的内存空间,最后返回destination指向内存空间的地址。
需要注意的是:如果source指向的内存空间与destination指向的内存空间有重叠的部分,memcpy处理的结果是未定义的,我们也可以这样理解,memcpy函数只需处理不重叠时的内存拷贝。后面内容会说到专门处理重叠问题的库函数memmove。
我们先看一下memcpy库函数的基本使用。请看代码:
//使用memcapy
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 6,7,8,9,10 };
//arr1指向的内存空间起始位置开始复制20字节内容到arr2中去
memcpy(arr2, arr1, 20);
//打印观察
for (int i = 0;i < 5;i++)
printf("%d ",arr2[i]);//此时打印1 2 3 4 5
return 0;
}
根据所描述的功能,我们可以写一个函数来模拟实现它,接下来请看代码:
//模拟实现memcpy
#include <assert.h>
#include <stdio.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);//判断指针的有效性
void* ptr = dest;//保存目的内存起始地址,防止丢失
while (num--)
{
//因为dest和src的类型都是void*,所以我们可以将其强制转换成char*类型
//一个字节一个字节的进行拷贝,直到num等于0为止
*(char*)dest = *(char*)src;
((char*)dest)++;
((char*)src)++;
}
return ptr;
}
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 6,7,8,9,10 };
//arr1指向的内存空间起始位置开始复制20字节内容到arr2中去
my_memcpy(arr2, arr1, 20);
//打印观察
for (int i = 0;i < 5;i++)
printf("%d ",arr2[i]);//此时打印1 2 3 4 5
return 0;
}
二、memmove库函数的使用和模拟实现
前面我们说到memcpy函数对内存重叠问题是未定义的,它只需解决未重叠的问题即可,那么memmove函数的出现则是专门用来解决内存重叠问题。
接下来,我们看一下memmove的基本使用。请看代码:
//使用memmove
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9 };
memmove(arr1 + 2, arr1, 20);
for (int i = 0;i < 9;i++)
printf("%d ",arr1[i]);//输出1 2 1 2 3 4 5 8 9
return 0;
}
我们也可以模拟实现它的功能。
接下来,请看具体代码:
//模拟实现memmove
#include <assert.h>
#include <stdio.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ptr = dest;//保存目的内存起始地址,防止丢失
if (src < dest)
{
//后->前
while (num--)
//找到最后一个字节的位置开始向前复制
*((char*)dest + num ) = *((char*)src + num );
}
else
{
//前->后
while (num--)
{
//因为dest和src的类型都是void*,所以我们可以将其强制转换成char*类型
//一个字节一个字节的进行拷贝,直到num等于0为止
*(char*)dest = *(char*)src;
((char*)dest)++;
((char*)src)++;
}
}
return ptr;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9 };
my_memmove(arr1 + 2, arr1, 20);
for (int i = 0;i < 9;i++)
printf("%d ", arr1[i]);//输出1 2 1 2 3 4 5 8 9
return 0;
}
三、memset库函数的使用和模拟实现
memset有3个参数,ptr是指向要填充的内存块的指针,value是要设置的值。该值以 int 形式传递,但该函数使用该值的无符号字符转换来填充内存块。num是要设置的字节的个数,返回起始位置的地址。
具体运用请看代码:
//使用memset
int main()
{
int arr[] = { 1,2,3,4,5,6 };
memset(arr, 0, 24);//将数组的内容全部设置为0
for (int i = 0;i < 6;i++)
{
printf("%d ",arr[i]);//打印结果为0 0 0 0 0 0
}
return 0;
}
下面我们可以模拟实现它,请看具体代码:
//模拟实现memset
#include <assert.h>
#include <stdio.h>
void* my_memset(void* ptr, int value, size_t num)
{
assert(ptr);//判断指针的有效性
void* tmp = ptr;
while (num--)
{
//将ptr强制转换为char*类型
//一位一位设置,直到num为0
*(char*)ptr = (unsigned char)value;
((char*)ptr)++;
}
return ptr;
}
int main()
{
//以int数据为例
//int arr[] = { 1,2,3,4,5,6 };
//my_memset(arr, 0, 24);//将数组的内容全部设置为0
//for (int i = 0;i < 6;i++)
//{
// printf("%d ",arr[i]);//打印结果为0 0 0 0 0 0
//}
//以字符串为例
char arr[] = "abcdef";
my_memset(arr, 'k', 6);
printf("%s\n",arr);//打印结果为kkkkkk
return 0;
}
四、memcmp库函数的使用和模拟实现
memcmp库函数的功能是比较从ptr1和ptr2指针指向的位置开始,向后的num个字节的内容。
它们的返回值有以下说明。
具体运用请看代码:
我们会发现它和strncmp非常相似,但我们要注意strncmp只能比较字符串,而memcmp可以比较任何类型,不仅限于比较字符串。
下面我们来模拟实现它,请看代码:
//模拟实现memcmp
#include <stdio.h>
#include <assert.h>
int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
assert(ptr1 && ptr2);//保证指针有效性
assert(num > 0);//num必须要大于0
while (*(char*)ptr1 == *(char*)ptr2)
{
num--;
if (num == 0)//如果num次数比较完了进循环就说明它们相等,返回0
return 0;
((char*)ptr1)++;
((char*)ptr2)++;
}
return *(char*)ptr1 - *(char*)ptr2;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcefg";
int ret = my_memcmp(arr1, arr2, 3);
if (ret > 0)
printf("'%s' is greater than '%s'.\n", arr1, arr2);
else if (ret < 0)
printf("'%s' is less than '%s'.\n", arr1, arr2);
else
printf("'%s' is the same as '%s'.\n", arr1, arr2);
return 0;
}
到这里就结束了,祝大家天天开心!