目录
一、内存函数的使用
1、memcpy()函数
memcpy()函数可以指定字节数,把源空间的内容拷贝到目的空间中 ,第一个参数是目的空间,第二个参数是源空间,第三个参数是指定的字节数,该函数的参数和返回值均为void*,可以接收任意类型数据的地址,该函数返回值是目标空间的起始地址。
cpp
//memcpy()函数
int main()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int arr1[10] = { 0 };
//想要把arr中的20个字节的数据拷贝到arr1中
memcpy(arr1, arr, 20);
for (int i = 0; i < 10; i++)
printf("%d ", arr1[i]);
printf("\n");
float arr2[10] = { 3.14f, 2.13f, 9.16f, 7.98f, 6.07f, 0.29f };
float arr3[10] = { 7.98f, 6.07f, 0.29f };
memcpy(arr2, arr3, 20);
for (int i = 0; i < 10; i++)
printf("%lf ", arr2[i]);
return 0;
}

注意:该函数拷贝同样要满足目标空间足够大,拷贝的字节数也不能乱指定。
2、memmove()函数
cpp
//memmove()函数
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]);//打印结果为:1 2 1 2 3 4 5 8 9 10
return 0;
}
memmove()函数的功能与memcpy()函数大致相同,只不过一个是可以原地拷贝,另一个是异地拷贝。
3、memcpy()函数
memcmp()函数是比较内存中指定字节内的数据。
cpp
//memcmp()函数
int main()
{
int arr1[10] = { 1, 2, 3, 4, 5 };
int arr2[10] = { 2, 4, 6, 8, 10 };
int arr3[10] = { 1, 2, 3, 4, 1 };
int arr4[10] = { 1, 2, 3, 4, 5 };
printf("%d\n", memcmp(arr1, arr2, 12));//打印结果为:-1
printf("%d\n", memcmp(arr1, arr3, 20));//打印结果为:1
printf("%d\n", memcmp(arr1, arr4, 20));//打印结果为:0
//该函数的返回值与strcmp相同,如果前者小于后者,返回负数,否则返回正数,相等返回0
return 0;
}
4、memset()函数:
cpp
//memset()函数
int main()
{
char str[] = "hello world!";
memset(str, 'x', 5);//将字符串str的前5个字节设置为'x'
printf("%s\n", str);//打印结果为:xxxxx world!
return 0;
}
**memset()函数可以指定字节数来设置内存,设置的值可以自己指定。**使用该函数时,不能设置常量字符串,另外指定的是字节数,不是元素个数。
cpp
//memset()函数
int main()
{
int arr[10] = { 0 };
memset(arr, 1, sizeof(arr));
for (int i = 0; i < 10; i++)
printf("%x\n", arr[i]);
return 0;
}

上面代码中,将arr数组中的元素的每一个字节都设置成了1。
二、内存函数的模拟实现
1、模拟实现memcpy()函数
cpp
//模拟实现memcpy()函数
void* my_memcpy(void* dest, const void* src, size_t size)
{
assert(dest && src);
void* ret = dest;
while (size--)
{
//void*指针不能直接解引用和加减运算
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;//这样写比((char*)dest)++更加稳定
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr[10] = { 1, 2, 3, 4, 5 };
int arr1[10] = { 10, 20, 30 };
my_memcpy(arr, arr1, 12);
for (int i = 0; i < 10; i++)
printf("%d ", arr[i]);//打印结果为:10 20 30 4 5 0 0 0 0 0
return 0;
}
下面演示自己设计的memcpy()函数在同一块空间的拷贝情况。
cpp
//模拟实现memcpy()函数在同一块空间拷贝
void* my_memcpy(void* dest, const void* src, size_t size)
{
assert(dest && src);
void* ret = dest;
while (size--)
{
//void*指针不能直接解引用和加减运算
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;//这样写比((char*)dest)++更加稳定
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
my_memcpy(arr + 2, arr, 20);//期望结果1 2 1 2 3 4 5 8 9 10
for (int i = 0; i < 10; i++)
printf("%d ", arr[i]);//打印结果为:1 2 1 2 1 2 1 8 9 10
//出现这种原因的情况是因为内存重叠时候,使用memcpy()函数可能会出问题
//那么如果在同一空间下拷贝,通常使用memmove()函数
return 0;
}
C语言的memcpy()函数主要拷贝不重叠的内存,重叠的内存由memmove()函数拷贝,虽然在VS编译器上使用memcpy()函数可能也能拷贝内存重叠的情况,这是因为VS编译器对memcpy()函数功能实现与memmove()函数相同,但不是所有的编译器都这样。
2、模拟实现memmove()函数
cpp
//模拟实现memmove()函数
void* my_memmove(void* dest, const void* src, size_t size)
{
//使用memcpy()函数出现了内存覆盖,是因为将内存前面的数据拷贝到后面时,运用了从前向后拷贝
//所以在实现memmove()函数时,如果将内存前面数据拷贝到后面,应该从后向前拷贝
//如果是将内存后面数据拷贝到前面,应该从前向后拷贝,这就分成两种情况讨论
//也就是dest<src时候,从前向后拷贝,dest>src时候,从后向前拷贝
assert(dest && src);
void* ret = dest;
if (dest < src)//从前向后拷贝
{
while (size--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else//从后向前拷贝
{
while (size --)
*((char*)dest + size) = *((char*)src + size);
}
return ret;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
my_memmove(arr + 2, arr, 20);
for (int i = 0; i < 10; i++)
printf("%d ", arr[i]);//打印结果为:1 2 1 2 3 4 5 8 9 10
return 0;
}