1 memcpy函数的使用和模拟实现
//memcpy函数的声明
void* memcpy(void* destination, const void* source, size_t num);
memcpy
函数可以给内存进行拷贝,由于不知道要拷贝的内存中存放的是哪一种类型的数据,所以memcpy
函数的返回类型设置成了void*
。
memcpy
函数在执行时,会从source
指向的位置开始向后复制num
个字节的数据到destination
指向的位置,期间在遇到\0
时并不会停下来,最后返回destination
的起始位置。
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 1,2,3,4,5,6,7,8 };
memcpy(arr1, arr2, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
输出结果:
注意:memcpy
函数可以处理不重叠的内存之间的数据拷贝,如果source
和destination
在内存上存在重叠,那么复制的结果将是未定义的。
有时候标准库中的memcpy
也能实现重叠拷贝(比如VS编译器),但是并不代表所有编译器的库函数中的memcpy
都能实现重叠拷贝。
#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memcpy(void* dest, void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
while (num)
{
//拷贝一个字节
*(char*)dest = *(char*)src;
//由于强制类型转换是临时的,所以想要地址+1也要强制转换
dest = (char*)dest + 1;
src = (char*)src + 1;
num--;
}
return ret;
}
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 1,2,3,4,5,6,7,8 };
char arr3[] = { 'a','b','c' ,'d' ,'e' ,'f','g','h','i' };
char arr4[] = "abcde";
my_memcpy(arr1, arr2, 20);
my_memcpy(arr3, arr4, 7);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
printf("%s\n", arr3);
return 0;
}
输出结果:
2 memmove函数的使用和模拟实现
//memmove函数的声明
void* memmove(void* destination, const void* source, size_t num);
和memcpy
函数相似,memmove
函数也可以给内存进行拷贝,不同的是memmove
函数处理的souce
和destination
的内存块是可以重叠的。
例:
#include <stdio.h>
#include <string.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr + 2, arr, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
输出结果:
memmove
函数模拟实现:
#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memmove(void* dest, void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
if (dest < src)//从前往后拷
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else//从后往前拷
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1, arr1 + 2, 20);
my_memmove(arr2 + 2, arr2, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
printf("\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
printf("\n");
return 0;
}
输出结果:
3 memset函数的使用
//memset函数的声明
void* memset(void* ptr, int value, size_t num);
memset
函数能将ptr
指向的内存块的前num
个字节设置为value
。
注意:memset
是以字节为单位设置内存值的。
例:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "hello world";
memset(arr, 'x', 5);
printf("%s\n", arr);
return 0;
}
输出结果:
4 memcmp函数的使用
//memcmp函数的声明
int memcmp(const void* ptr1, const void* ptr2, size_t num);
memcmp
函数能够比较从ptr1
和ptr2
指针指向的位置开始向后的num
个字节,其返回值如下:
返回值 | 含义 |
---|---|
<0 | 两个内存块中不匹配的第一个字节ptr1 中的值小于ptr2 中的值(如果评估为无符号字符值) |
0 | 两个内存块的内容相等 |
>0 | 两个内存块中不匹配的第一个字节在ptr1 中的值大于在ptr2 中的值(如果评估为无符号字符值) |
例:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "aacdef";
char arr2[] = "abcdef";
char arr3[] = "abcdef";
char arr4[] = "accdef";
int ret1 = memcmp(arr1, arr2, 2);
int ret2 = memcmp(arr2, arr3, 2);
int ret3 = memcmp(arr4, arr3, 2);
printf("%d\n", ret1);
printf("%d\n", ret2);
printf("%d\n", ret3);
return 0;
}
输出结果: