2010-08-26 18 views
5

¿Puede alguien ayudarme a entender cómo se implementa memmove en C. Tengo solo una condición especial, cierto?Implementación de memmove en C

if((src<dst)&&((src+sz) > dst)) 

copy from the back 

¿Depende también de cómo crece la pila?

+0

Si 'src',' dst', y 'sz' son todos valores positivos, la condición no es satisfactoria. Si 'src> dst', agregar' sz' positivo no lo hará menos. – Edmund

+0

@Edmund He corregido – brett

Respuesta

28

Matemáticamente, no tiene que preocuparse de si se superponen en absoluto. Si src es menor que dst, solo copie desde el final. Si src es mayor que dst, solo copie desde el principio.

Si src y dst son iguales, solo salga de inmediato.

Eso es debido a que sus casos son uno de:

1) <-----s----->    start at end of s 
       <-----d-----> 

2) <-----s----->    start at end of s 
      <-----d-----> 

3) <-----s----->    no action 
    <-----d-----> 

4)   <-----s----->  start at beginning of s 
    <-----d-----> 

5)    <-----s-----> start at beginning of s 
    <-----d-----> 

Incluso si no hay solapamiento, que todavía funciona bien, y simplifican sus condiciones.

Si tiene una forma más eficiente de copiar hacia adelante que hacia atrás, sí, debe verificar la superposición para asegurarse de que está utilizando el método más eficiente si es posible. En otras palabras, cambie la opción 1 anterior para copiar desde el principio.

+1

Tenga en cuenta que hay Otra suposición oculta aquí, que es que solo estás copiando un byte a la vez. – caf

+2

Bueno, ya sea que copies un byte a la vez, o un quadword o algún valor masivo de hyperword de SSE9 de 1024 bits, la teoría sigue siendo la misma.Debe asegurarse de no copiar _en_un área de superposición que aún no ha copiado _ fuera de_. Todas las opciones N-es-ancho-que-char introducen es una detección algo más compleja de superposición (y transferencia final) en el caso en que no es un múltiplo directo del valor de N. – paxdiablo

+0

@caf: If 'src' y 'dest' tiene la misma alineación con respecto a un tipo más grande que podría copiar, nunca tendrá que preocuparse por golpear un área que aún no ha copiado, ya que las posiciones siempre diferirán en al menos ese tamaño. Si no comparten la misma alineación, estás atascado copiándolos como bytes de todos modos ... a menos que quieras utilizar algún io desagradable x86 ... –

1

Depende del compilador. Los buenos compiladores usarán buenas optimizaciones dependiendo del conjunto de instrucciones del procesador de destino y el ancho del bus.

+0

Creo que esto debería ir en un comentario en lugar de la respuesta por separado – YeenFei

5

memmove puede convertirse en una memcpy si las dos regiones de memoria no se superponen. Obviamente, memcpy está extremadamente optimizado en la mayoría de los sistemas (uno de los que uso hace uso de casi todos los trucos en el libro, desde bucles desenrollados hasta operaciones SSE donde se admite el máximo rendimiento).

Si las dos regiones de memoria se superponen, la región que se va a copiar se mueve a un búfer temporal y el búfer temporal se copia (todo con memcpy, probablemente) de nuevo en la parte superior del búfer original. No puede trabajar desde el principio o trabajar desde la parte posterior con una región superpuesta, porque siempre terminará con al menos algunos datos dañados en el proceso.

Dicho esto, ha pasado mucho tiempo desde que eché un vistazo al código libc, por lo que puede haber una optimización para memmove y regiones superpuestas que aún no he pensado.

memmove no depende de la forma en que crezca la pila, simplemente copia una región de la memoria en otra ubicación, exactamente como memcpy, excepto que maneja regiones superpuestas y memcpy no.

EDITAR: En realidad, pensar en ello un poco más ... Trabajar desde la parte posterior puede funcionar si vas desde la "fuente" correcta (por así decirlo), dependiendo del movimiento en sí (por ejemplo, es fuente < dest o ¿no?). Puede leer la implementación de newlib here, y tt también está bastante bien comentado.

+0

Me gustaría verte copiar en un búfer temporal cuando 'n' es' SIZE_MAX >> 1' ... –