memcpy (z anglického memory copy - copying memory) je funkce standardní knihovny programovacího jazyka C , která kopíruje obsah jedné paměťové oblasti do druhé.
Funkce je definována v záhlaví souboru string.h (a také v mem.h ), popsaném v normách ANSI C a POSIX .
Aby se neprováděly zbytečné akce, funkce memcpy() nekontroluje, zda velikost výstupní vyrovnávací paměti odpovídá počtu zkopírovaných bajtů, takže tuto odpovědnost ponechává na programátorovi. V důsledku toho se dělá poměrně hodně chyb, které mohou vést k přetečení vyrovnávací paměti.
Proto ke konci roku 2009 společnost Microsoft přidala memcpy(), CopyMemory() a RtlCopyMemory() na seznam funkcí zakázaných podle metodiky vývoje zabezpečeného softwaru Secure Development Lifecycle (SDL). Ti vývojáři, kteří chtějí vytvářet aplikace kompatibilní s SDL, budou muset použít funkci memcpy_s místo memcpy(), která vám umožní určit velikost vyrovnávací paměti. Funkce memcpy_s() není přenosná a není součástí standardu C.
kde:
Funkce zkopíruje n bajtů z oblasti paměti, na kterou ukazuje src , do oblasti paměti, na kterou ukazuje dst . Funkce vrací cílovou adresu dst .
Oblasti paměti se nesmí překrývat , jinak se data nemusí správně zkopírovat, například takto:
__src___ | | 1234567890 xxxxx |_____| dstpo zkopírování obsahuje vyrovnávací paměť dst data odlišná od původních, protože byla zničena během procesu kopírování:
__dst___ | | 12 1212121212 xxxCo se skutečně stane, závisí na implementaci funkce (příklad odkazuje na jednu z implementací níže).
Chcete-li správně zkopírovat překrývající se oblasti, použijte funkci memmove (). Některé implementace memcpy() (např. v libc FreeBSD a OpenBSD ) dělají totéž jako memmove(), nutí i špatně napsané programy, aby fungovaly správně, ale při psaní přenosného programu v to nelze doufat .
memcpy() zkopíruje obsah src do vyrovnávací paměti dst , takto:
int i ; pro ( i = 0 ; i < n ; i ++ ) (( unsigned char * ) dst )[ i ] = (( unsigned char * ) src )[ i ]; vrátit dst ;Tento příklad však poběží pomaleji než jakékoli praktické implementace, protože jsou optimalizovány:
Příklad částečně optimalizované verze:
int i , m ; unsigned long * wdst = dst ; // aktuální pozice v cílovém bufferu unsigned long * wsrc = src ; // aktuální pozice ve zdroji unsigned char * cdst , * csrc ; for ( i = 0 , m = n / sizeof ( long ); i < m ; i ++ ) // zkopírujte hlavní část do bloků po 4 nebo 8 bytech * ( wdst ++ ) = * ( wsrc ++ ); // (závislé na platformě) cdst = ( unsigned char * ) wdst ; csrc = ( unsigned char * ) wsrc ; for ( i = 0 , m = n % sizeof ( long ); i < m ; i ++ ) // zkopírujte zbytek byte po byte * ( cdst ++ ) = * ( csrc ++ ); vrátit dst ;Tato verze zkopíruje 4 nebo 8 bajtů (délka je 32 bitů) za cyklus, ale nekontroluje zarovnání dat.