这个 memcpy 函数用于将数据块从源地址复制到目标地址。下面是它的原型。
null
void * memcpy(void * destination, const void * source, size_t num);
其思想是简单地将给定的地址类型转换为char*(char需要1字节)。然后一个接一个地将数据从源复制到目标。下面是这个想法的实现。
// A C implementation of memcpy() #include<stdio.h> #include<string.h> void myMemCpy( void *dest, void *src, size_t n) { // Typecast src and dest addresses to (char *) char *csrc = ( char *)src; char *cdest = ( char *)dest; // Copy contents of src[] to dest[] for ( int i=0; i<n; i++) cdest[i] = csrc[i]; } // Driver program int main() { char csrc[] = "GeeksforGeeks" ; char cdest[100]; myMemCpy(cdest, csrc, strlen (csrc)+1); printf ( "Copied string is %s" , cdest); int isrc[] = {10, 20, 30, 40, 50}; int n = sizeof (isrc)/ sizeof (isrc[0]); int idest[n], i; myMemCpy(idest, isrc, sizeof (isrc)); printf ( "Copied array is " ); for (i=0; i<n; i++) printf ( "%d " , idest[i]); return 0; } |
输出:
Copied string is GeeksforGeeks Copied array is 10 20 30 40 50
是什么 memmove() ?
memmove()与memcpy()类似,因为它还将数据从源复制到目标。当源地址和目标地址重叠时,memcpy()会导致问题,因为memcpy()只是将数据从一个位置逐个复制到另一个位置。例如,考虑下面的程序。
// Sample program to show that memcpy() can lose data. #include <stdio.h> #include <string.h> int main() { char csrc[100] = "Geeksfor" ; memcpy (csrc+5, csrc, strlen (csrc)+1); printf ( "%s" , csrc); return 0; } |
输出:
GeeksGeeksfor
由于输入地址重叠,上述程序会覆盖原始字符串并导致数据丢失。
// Sample program to show that memmove() is better than memcpy() // when addresses overlap. #include <stdio.h> #include <string.h> int main() { char csrc[100] = "Geeksfor" ; memmove (csrc+5, csrc, strlen (csrc)+1); printf ( "%s" , csrc); return 0; } |
输出:
GeeksGeeksfor
如何实现memmove()?
这里的技巧是使用临时数组,而不是直接从src复制到dest。使用临时数组对于处理源地址和目标地址重叠的情况非常重要。
//C++ program to demonstrate implementation of memmove() #include<stdio.h> #include<string.h> // A function to copy block of 'n' bytes from source // address 'src' to destination address 'dest'. void myMemMove( void *dest, void *src, size_t n) { // Typecast src and dest addresses to (char *) char *csrc = ( char *)src; char *cdest = ( char *)dest; // Create a temporary array to hold data of src char *temp = new char [n]; // Copy data from csrc[] to temp[] for ( int i=0; i<n; i++) temp[i] = csrc[i]; // Copy data from temp[] to cdest[] for ( int i=0; i<n; i++) cdest[i] = temp[i]; delete [] temp; } // Driver program int main() { char csrc[100] = "Geeksfor" ; myMemMove(csrc+5, csrc, strlen (csrc)+1); printf ( "%s" , csrc); return 0; } |
输出:
GeeksGeeksfor
优化: 该算法效率低下(如果使用临时数组,时间会增加一倍)。除非真的不可能,否则应该避免双重复制。
但在这种情况下,通过选择复制方向可以很容易地避免双重复制。事实上,这就是memmove()库函数的作用。
通过比较src和dst地址,您应该能够发现它们是否重叠。
–如果它们不重叠,您可以向任何方向复制 –如果它们确实重叠,找出dest的哪一端与源重叠,并相应地选择复制方向。 –如果dest的开头重叠,则从结尾复制到开头 –如果dest的结尾重叠,则从开始复制到结束 –另一个优化是按字数复制。只是要小心处理边界条件。 –由于向量指令是连续的,所以进一步的优化将是对副本使用向量指令。
本文由Saurabh Jain撰稿。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END