2012-11-12 4 views
10

Dalla pagina di manuale Linux per memmove(3)Perché Linux memmove() è implementato così com'è?

I memmove) copie (funzione n byte da un'area di memoria src per area di memoria dest. Le aree di memoria possono sovrapporsi: la copiatura avviene come se i byte in src fossero prima copiati in una matrice temporanea che non si sovrappone a src o dest, e quindi i byte vengano copiati dall'array temporaneo a dest.

Invece di allocare una matrice temporanea e copiare i valori due volte potremmo effettuare le seguenti operazioni:

void *my_memmove(void *dest, const void *src, size_t n) { 
    signed char operation; 
    size_t end; 
    size_t current; 

    if(dest != src) { 
    if(dest < src) { 
     operation = 1; 
     current = 0; 
     end = n; 
    } else { 
     operation = -1; 
     current = n - 1; 
     end = -1; 
    } 

    for(; current != end; current += operation) { 
     *(((unsigned char*)dest) + current) = *(((unsigned char*)src) + current); 
    } 
    } 
    return dest; 
} 

In questa implementazione semplicemente occupiamo della posizione in cui si comincia a copiare.

C'è un inconveniente nella mia implementazione?

Nota: in realtà non userò la mia implementazione. Sono solo curioso.

+4

'dest

+12

Penso che tu abbia perso "come se" nella manpage. In realtà non funziona in questo modo. – dbrank0

+0

Puoi confrontare la tua implementazione con [FreeBSD's 'bcopy'] (http://fxr.watson.org/fxr/source/string/bcopy.c?v=FREEBSD-LIBC), il codice sottostante per il loro memmove(). Supporta anche la copia all'indietro, senza un buffer temporaneo. – ShiDoiSi

risposta

22

Potete guardare qualche codice sorgente per memmove here, here, here e here.

Quello che noterete è che non lo fanno in realtà fare un array temporaneo. Le pagine man sono scritte per aiutarti a capire cosa sta facendo logicamente, non in realtà. Quindi, dicono "come se".

Che memmove() in realtà non fa altro che copiare il byte da src a dest, e le copie avanti se dest < src (che è essenzialmente la stessa cosa di memcpy), e indietro altrimenti.

La differenza tra memcpy e memmove è che memcpy ciecamente copie avanti - che è il motivo per cui dest e src non deve sovrapporsi. Ma memmove prende la precauzione di assicurare che la sovrapposizione non rovini il risultato finale.

+2

Punti eccellenti. Il memmove da C source a Linux è [qui] (http://sourceware.org/git/?p=glibc.git;a=blob;f=string/memmove.c;h=bf7dcc162770503ed62a262f627bfa526fc5a0d7;hb=HEAD), ma è in gran parte irrilevante perché il memmove reale è implementato [in assembly ottimizzato a mano] (http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86_64/memcpy.S; h = 9e693f2a9806fa8f6ce7e26f37b1808e952396d3; hb = HEAD), che definietely non copia su un array temporaneo. Come curiosità, è definito esattamente come 'memcpy', perché sulla sua architettura di destinazione non c'è penalità dal farlo in quel modo. – user4815162342