精密模具东莞网站建设,上海做什么工作最赚钱,公司网站销售怎么做的,山东建设局网站首页本篇文章目录 相关文章1. 模拟 memcpy 内存拷贝2. 模拟 memmove 内存移动 相关文章
【C语言】数据在内存中是以什么顺序存储的#xff1f;【C语言】整数在内存中如何存储#xff1f;又是如何进行计算使用的#xff1f;【C语言】利用void*进行泛型编程【C语言】4.指针类型部… 本篇文章目录 相关文章1. 模拟 memcpy 内存拷贝2. 模拟 memmove 内存移动 相关文章
【C语言】数据在内存中是以什么顺序存储的【C语言】整数在内存中如何存储又是如何进行计算使用的【C语言】利用void*进行泛型编程【C语言】4.指针类型部分 使用内存库函数实际上要包含string.h头文件这个大伙要注意。 1. 模拟 memcpy 内存拷贝 两个指针的指向必须是两块互相独立的内存区域即两个不同的数组。 dest空间必须比src空间大 bytes表示要从src拷贝到dest的字节数。 // void* 通用的泛型编程可以接收任何指针
void* my_memcpy(void* dest, const void* src, size_t bytes) {assert(dest src);if (dest src) {return dest;}void* t dest;while (bytes--) {// 不清楚void*接收的是什么类型指针直接char*一个个字节拷贝。*(char*)dest *(char*)src;dest (char*)dest 1;src (char*)src 1;/*((char*)dest);((char*)src);---------------((char*)dest);((char*)src);这两种写法换成c都不行*/}return t;
}
int main() {int arr1[] { 1, 2, 3, 4, 5, 6, 7, 8 };int arr2[] { 1, 2, 3, 4};my_memcpy(arr1 4, arr2, sizeof(int) * 4);for (int i 0; i 8; i) {printf(%d , arr1[i]);}return 0;
}对于标准的memcpy如果不进行完善实际上是有问题的假设有一个数组 int arr[] { 1, 2, 3, 4, 5, 6, 7, 8 }指针dest和指针src两个指针指向同一个数组内存并且以字节为单位进行内存移动会出现几种情况
1.dest和src指向同一个地址如my_memcpy(arr, arr, 4)等于啥也没动2.dest指向地址值大于src2.1 如my_memcpy(arr 4, arr, 16)也就是将5 6 7 8改成1 2 3 4结果为1 2 3 4 1 2 3 4-----------------------------------------------------2.2 如my_memcpy(arr 2, arr, 16)也就是将3 4 5 6改成1 2 3 4即 1 2 1 2 3 4 7 8但结果会变成1 2 1 2 1 2 7 8因为原来3 4位置被改成了1 2。3.dest指向地址值小于src3.1 如my_memcpy(arr, arr 4, 16)也就是将1 2 3 4改成5 6 7 8结果为5 6 7 8 5 6 7 8-----------------------------------------------------3.2 如my_memcpy(arr, arr 2, 16)也就是将1 2 3 4改成3 4 5 6结果为 3 4 5 6 5 6 7 8。到这里会发现也就只有2.2的结果不是我们想要的这是因为自己实现的memcpy并不不完善如果是string.h库函数中的memcpy则不存在这个问题。 本来是要将3 4 5 6改成1 2 3 4结果改成了1 2 1 2。
事实上对于memcpy函数C语言标准定义的是两个指针指向的内存位置不能是同一块区域但显然对于vs2022的编译器而言是将memcpy完善了。但我们使用时还是尽量不要将两个指针指向同一个数组内的元素地址毕竟要考虑到其它编译器并不一定完善。
画图分析2.2 my_memcpy(arr 2, arr, sizeof(int) * 4) 图中每个格子代表arr数组中的一个元素每个元素四个字节。我们利用这个简单的图分析上面模拟实现memcpy的代码不难看出实际上拷贝是从前往后进行拷贝的也就是从src、dest的起始位置开始往后拷贝。当拷贝完8个字节后就变成了下面的样子 这时的3和4早已被拷贝成了1和23和4不存在了。那么5和6就无法被拷贝成3和4了自然而然也变成了1和2。
而解决这个问题使用库函数memmove最好对于这个函数C语言的使用标准是这样的两个指针既可以指向同一块内存区域也可以像memcpy一样两个指针指向不同内存区域。
2. 模拟 memmove 内存移动 如果自己实现memmove通过上面例子出现的问题同一块数组内存区域如果要解决该问题要考虑到的情况实际上也就是从前往后还是从后往前拷贝的问题这个得由dest和src的地址大小比较后决定。 就对于上面模拟实现memcpy的问题如果是从后往前拷贝比如把6改成4再把5改成3再把3改成2把2改成1互不影响那么问题迎刃而解但如果大伙认为真这么简单那就打错特错了。
对于内存而言以字节为单位1个整型4个字节我们实际上是要从最后一个字节开始往前一个个字节拷贝。arr数组的内存布局如下 每一格都是1个字节四格则构成一个完整的整型数据也就是arr数组中的一个元素。格子中的值是用十六进制表示的至于为什么是倒着存储的这是因为当前机器以小端字节序存储数据详细了解请看本篇文章最上面的 相关文章位置第一个链接中的文章有解释。
则对于dest地址值大于src的情况可以这样拷贝 而对于dest地址值小于src的情况照常从前往后拷贝
//模拟memmove两个指针的指向可以是两块互相独立内存也可以是同一块内存
void* my_memmove(void* dest, const void* src, size_t bytes) {assert(dest src);void* t dest;// 从后面最后一个字节往前将6改成4再将5改成34改成23改成1解决上面memcpy 2.2中的问题if (dest src) {while (bytes--) { *((char*)dest bytes) *((char*)src bytes);}} else if (dest src) { while (bytes--) {*(char*)dest *(char*)src;dest (char*)dest 1;src (char*)src 1;}} return t;
}int main() {int arr[] { 1, 2, 3, 4, 5, 6, 7, 8 };my_memmove(arr, arr 2, sizeof(int) * 4);for (int i 0; i 8; i) {printf(%d , arr[i]);}return 0;
}成功把3 4 5 6改成1 2 3 4 把1 2 3 4改成3 4 5 6也没问题