memcpy(不重复地址拷贝)
语法格式
在C语言中,`memcpy` 是一个标准库函数,用于在内存之间复制数据。它的原型定义在 `<string.h>` 头文件中。`memcpy` 的语法格式如下:
```c
void *memcpy(void *destination, const void *source, size_t num);
```
参数说明:
- `destination`: 指向目标内存块的指针,即将要复制数据到的位置。
- `source`: 指向源内存块的指针,即数据的起始位置。
- `num`: 要复制的字节数。
`memcpy` 函数会从 `source` 指向的内存位置开始,复制 `num` 个字节到 `destination` 指向的内存位置。请注意,`memcpy` 不会检查目标内存是否足够大以容纳要复制的数据,这可能会导致未定义行为,如内存越界。
示例用法:
```c
#include <stdio.h>
#include <string.h>
int main() {
int src[] = {1, 2, 3, 4, 5};
int dest[10];
// 复制数组 src 的前 5 个元素到 dest
memcpy(dest, src, 5 * sizeof(int));
// 打印结果
for (int i = 0; i < 5; i++) {
printf("%d ", dest[i]);
}
printf("\n");
return 0;
}
在这个例子中,`memcpy` 被用来复制 `src` 数组的前 5 个元素到 `dest` 数组中。
具体说明
memcpy这个是拷贝内存快 什么都能拷贝
函数的返回类型是void*
void*类型也就说明 计算的时候是需要强制类型转化的 因为void的类型是无法计算的
使用规则 num 拷贝长度 这里是长度的大小是字节的大小,因为是地址的拷贝,也就是有可能是拷贝字符,这样的情况下只能是拷贝一个字节一个字节拷贝的情况下才能完成。
这里arr1 和arr2不要有内存的重叠
函数的模拟实现
src源头
num长度
这里不能写成int* 因为int*也就是说明类型固定
所以只能是void*(这里针对各种类型的类型)这里可以加上const
这里说明返回目标空间的起始地址
图解
这里是20个字节 这个数组是20个元素 80个字节 不能理解错了 这个数组不是20个字节
这里还是一个字节一个字节的拷贝
20个字节传递5个元素
这里使用char*指类型的指针解应用是最好的选择
也就这里是一个字节一个字节的交换 相当于strstr
完整代码
这里强制类型转化是不行的 因为强制类型转化是临时的
除非这样
版本2
这里说明 已经放1 2 了此时3 准备放到5的时候 此时 3 本身的位置变成1 所以也就是1 2 1 2 1 2 1 8 9 10
这里可以加上const 在source里面 因为source是被拷贝的地址 我们是不希望进行改变的
代码总结
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest, void* src, size_t num)
{
assert(dest && src);
while (num--)
{
*(char*)dest = *(char*)src;//void类型是不能进行计算的 只能进行强制类型转化 要转化成char*类型的原因是 一方面这个是指针 另一方面这个是按照字节大小进行计算拷贝的
dest = (char*)dest + 1;
src = (char*)src + 1;//或者写成这样 这里强制类型转化的情况下
//src=((char*)(src))++;这样的话可以++
}
}
void* MY_memcpy(void* str1, void* str2, size_t num)
{
assert(str1 && str2);
while (num--)//这里是每次计算的时候减少一个字节 所以会直到为0 的时候自己跳出循环
{
*(char*)str1 = *(char*)str2;//进行强制类型转化的原因是因为这里是void类型 void类型是无法参与计算的 所以要进行强制类型转化
str1 = (char*)str1 + 1;//这里不能和拷贝库函数一样直接++ 因为void是无法参与计算的
str2 = (char*)str2 + 1;
}
}
int main()
{
char arr1[] = "sdfhilbgjju ";
char arr3[100] = { 0 };
memcpy(arr3, arr1, 20);//这里是拷贝空间和被拷贝空间 num是字节大小 不是
printf("%s \n", arr3);
int arr2[] = { 1,2,3,4,5,6,7,8,9 };
int arr4[100] = { 0 };
memcpy(arr4, arr2, 20);
for (int i = 0; i < 20; i++)
{
printf("%d ", arr4[i]);
}
printf("\n");
//模拟memcpy函数
int arr5[] = { 1,2,3,4,5,6,7,8,9 };
int arr6[100] = { 0 };
my_memcpy(arr6, arr5, 20);
for (int i = 0; i < 20; i++)//这里的20 不是二十字节 而是二十个数值
{
printf("%d ", arr6[i]);//这里是直接打印数组
}
printf("\n");
//二次模拟memcpy函数
int str1[] = { 1,2,3,4,5,6,7,8,9 };
int str2[100] = { 0 };
MY_memcpy(str2, str1, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", str2[i]);
}
return 0;
}
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————