目录
一.memcpy 使⽤和模拟实现 - 内存拷贝
1.使用
void* memcpy(void* destination, const void* source, size_t num);
参数:3个
destination:目的地 - 里面内容是会变的
source:源头 - 里面内容是不会变的,用cosnt修饰
num:拷贝num个字节
源头拷贝到目的地,拷贝num个字节,参数void*,为什么?因为可能拷贝任何数据。
返回类型:void*
重要点:
• 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。
• 这个函数在遇到 '\0' 的时候并不会停下来。strcpy拷贝到\0就停下来。
而memcpy你让我拷贝多大就拷贝多大,即使有\0照样拷贝。
• 如果source和destination有任何的重叠,复制的结果都是未定义的。//一般拷贝的是内存不重叠的情况
memcpy使用在内存不重叠拷贝,如果拷贝内容是重叠/同一块内存空间,就不要使用这个函数。
代码举例:memcpy函数整形拷贝
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
//将arr1中的1 2 3 4 5,拷贝到arr2中
memcpy(arr2, arr1, 5 * sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
代码举例:memcpy函数字符数数组拷贝
int main()
{
char arr1[10] = "hello bit";
char arr2[10] = { 0 };
memcpy(arr2, arr1, 5);
int i = 0;
//for (i = 0; i < 5; i++)
//{
// printf("%c", arr2[i]);
//}
printf("%s", arr2);
return 0;
}
总结:我们可能传递字符的地址,也有可能传递整形地址,所以我们参数用void*类型。
代码举例:探究memcpy拷贝字符串遇到\0会不会拷贝后面字符
int main()
{
char arr1[10] = "he\0lo bit";
char arr2[10] = { 0 };
memcpy(arr2, arr1, 5);
int i = 0;
for (i = 0; i < 5; i++)
{
printf("%c ", arr2[i]);
}
return 0;
}
你让我拷贝几个就拷贝几个,不会管\0。
2.memcpy函数模拟实现
void* my_memcpy(void* dest, const void* src, size_t num)
{
while (num--)
{
*(char*)dest = *(char*)src;//强制类型转换是临时的效果,下面也要强制类型转换
//强制转换方法1:这种写法在有些编译器跑步过去
//((char*)dest)++;
//((char*)src)++;
//强制转换方法2:加完的结果放在dest和src
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
//将arr1中的4 5 6 7 8,拷贝到arr2中
my_memcpy(arr2, arr1 + 3, 5 * sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
代码举例:探究memcpy拷贝同一块空间的结果?
void* my_memcpy(void* dest, const void* src, size_t num)
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };//12345,拷贝到34567上面去,内容重叠
my_memcpy(arr1+2, arr1, 5 * sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1 [i]);//1 2 1 2 1 2 1 8 9 10
}
return 0;
}
因为拷贝3 4的时候被改成1 2,拷贝5 6的时候因为3 4被改成1 2所以5 6也是1 2 ,内容重叠拷贝结果就是错误。
总结:
1.强制类型是临时的。
2.arr1数组拷贝到arr2数组里面,这是2块完全独立的空间,没有任何重叠和交错。
3.对应重叠的内存,交给memmove函数处理。
二.memmove使⽤和模拟实现
1.使用
void* memmove(void* destination, const void* source, size_t num);
memmove的参数和返回值跟memcpy差不多,所以使用方法也差不多。
代码举例:
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr1 + 2, arr1, 5 * sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
2.memmove模拟实现
void* my_memmove(void* dest, const char* src, size_t num)
{
void* ret = dest;
assert(dest && src);
if (dest < src)
{
//前—>后指针在动
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
//后—>前num在动
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1, 5 * sizeof(int));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
分析:如何拷贝?
空间重叠的时候:
1.从前向后拷贝 - dest在src左边 - dest < src
2.从后向前拷贝 - dest在src右边 - dest > src
空间不重叠的时候:就不需要考虑从前向后还是从后向前拷贝。
从后向前拷贝怎样拷贝?
1.分别拿到dest和src的末尾地址;+个num就可以拿到地址。
C语言中规定:
memcpy:拷贝的就是不重叠内存
memmove:拷贝的是重叠内存
但是在vs2022memcpy也可以实现重叠拷贝。
三.memset函数的使⽤ - 内存设置
void* memset(void* ptr, int value, size_t num);
参数:
ptr:你要设置那块内存,从哪开始。
value:你要设置的值是什么
num:要设置为值的字节数
ptr指向的且num个字节内容设置成value值。
代码举例:字符数组
int main()
{
char arr[10] = "hello bit";
memset(arr, 'x', 5);
printf("%s\n", arr);
return 0;
}
memset 在设置的时候,是以字节为单位来设置的
代码举例:整形数组 - 想把数组10个元素的值改成1
int main()
{
int arr[10] = { 0 };
memser(arr, 1, 10);//错误:首先这个数组是40个字节,
memser(arr, 1, 40);//错误:当你改成40,它会把每个字节改成1
//0x01010101
return 0;
}
总结:当你内存设置的值不满意的时候,就可以用memset来设置成你想要的值。
四.memcmp函数的使用 - 进行内存比较
int memcmp(const void* ptr1, const void* ptr2, size_t num);
这个函数跟strcmp非常相似,只不过它能进行内容比较,什么样的内存都能比较。
参数:
• ⽐较从ptr1和ptr2指针指向的位置开始,向后的num个字节。
返回值:
ptr1 > ptr2;>0
ptr1 = ptr2; 0
ptr1 < ptr2;<0
代码举例:整形比较
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[] = { 1,2,3,4,8 };
int ret = memcmp(arr1, arr2, 17);
printf("%d\n", ret);//-1
return 0;
}
代码举例:字符比较
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdef";
int ret = memcmp(arr1, arr2, 7);
printf("%d\n", ret);//0
return 0;
}