2011-03-15 8 views
5

¿Esto está bien?memcpy copiando parcialmente sobre sí mismo

char buf[] = { 0, 1, 2 }; 
memcpy(buf, buf + 1, 2); 

¿Tener un tipo de datos más grande hace alguna diferencia? Sé que podría usar memmove(), pero solo tengo curiosidad.

+0

-1: ¿qué pasó cuando lo intentó? – pmg

+3

+1, porque no estoy de acuerdo con pmg's -1. "¿Qué pasó cuando lo buscaste en el estándar?", Tal vez, pero existe un riesgo real al experimentar con este tipo de cosas, que puedes probarlo y "funciona", con el resultado '{1,2,2} 'en el buffer. Entonces, ¿de qué sirve el consejo para probarlo? ¿Seguirá funcionando la próxima semana, o cuando active la optimización, o en las computadoras de sus clientes? –

+0

@Steve Jessop: Estoy de acuerdo. El ejemplo del OP (probablemente) funcionará, dependiendo de la implementación particular de la plataforma objetivo de 'memcpy', ¡pero eso no lo hace una buena idea! – GrahamS

Respuesta

12

Los efectos de memcpy no se definen cuando la entrada y la salida se superponen. Debe usar memmove.

5

No está bien. Usted debe utilizar memmove cuando la fuente y el destino se superponen.

puede trabajar con memcpy, dependiendo de la implementación de su compilador, pero eso no es algo en lo que deba confiar.


Una aplicación típica ingenua podría ser una copia byte a byte (uint8) así:

typedef unsigned char uint8; 

void * memcpy (void * destination, const void * source, size_t num) 
{ 
    const uint8* pSrc = (const uint8*)source; 
    const uint8* const pSrcEnd = pSrc + num; 
    uint8* pDst = (uint8*)destination; 

    while (pSrc != pSrcEnd) 
     *(pDst++) = *(pSrc++); 

    return destination; 
} 

que trabajaría bien con su memcpy(buf, buf + 1, 2), pero menos bien con memcpy(buf + 1, buf, 2)

3

El comportamiento no está definido si las regiones de memoria se superponen, por lo que no está bien.

1

Es un comportamiento indefinido, pero lo he utilizado como tal,

char buf[] = {0, 1, 2, 3); 
memcpy(buf, buf+2, 2); 

donde el punto final de destino es menor que el punto de inicio de la fuente. Debería seguir utilizando memmove para estar seguro ...

+0

La biblioteca GNU C ha cambiado la implementación de memcpy unas pocas veces. A veces es incluso diferente para i686 vs i386 vs x86_64. –