Memcpy

Aktuální verze stránky ještě nebyla zkontrolována zkušenými přispěvateli a může se výrazně lišit od verze recenzované 8. června 2016; kontroly vyžadují 10 úprav .

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 .

memcpy_s

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.

Definice

void * memcpy ( void * dst , const void * src , size_t n );

kde:

  • dst - adresa cílové vyrovnávací paměti
  • src - zdrojová adresa
  • n - počet bajtů ke kopírování

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 |_____| dst

po 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 xxx

Co 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 .

Algoritmus provozu a implementace

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:

  • Nepoužívejte indexy, jako v příkladu.
  • V jednom cyklu neposunou jeden bajt, ale blok rovný strojovému slovu (2, 4 nebo 8 bajtů ; 16, 32 nebo 64 bitů ), který je zkopírován procesorem ve stejnou dobu jako bajt. Tento přístup je nejúčinnější při kopírování dat zarovnaných na hranici slova stroje.
  • Někdy se pro práci s datovými bloky používají instrukce procesoru (movsX pro i386 ), v tomto případě je funkce napsána pomocí assembleru

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.

Příklad použití

#include <řetězec.h> pole int bez znaménka [ 512 ]; // zdroj unsigned char byte_array [ sizeof ( pole ) * sizeof ( unsigned int )]; // cílová vyrovnávací paměť memcpy ( byte_array , pole , sizeof ( byte_array ));

Odkazy

Viz také